├── .gitignore ├── README.md ├── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── images ├── cf.png ├── cf2.png ├── cf3.png └── cf4.png ├── out └── production │ └── spring-boot-starter-chatbot │ └── META-INF │ └── spring.factories └── src └── main ├── java └── com │ └── kingbbode │ └── chatbot │ └── autoconfigure │ ├── ChatbotAutoConfiguration.java │ ├── ChatbotProperties.java │ ├── TeamUpAutoConfiguration.java │ ├── TeamUpProperties.java │ ├── api │ ├── AbstractBotApi.java │ ├── ApiData.java │ └── BotApi.java │ ├── base │ ├── BaseBrain.java │ ├── emoticon │ │ ├── brain │ │ │ └── EmoticonBrain.java │ │ └── component │ │ │ └── EmoticonComponent.java │ ├── knowledge │ │ ├── brain │ │ │ └── KnowledgeBrain.java │ │ └── component │ │ │ └── KnowledgeComponent.java │ └── stat │ │ └── StatComponent.java │ ├── brain │ ├── DispatcherBrain.java │ ├── aop │ │ └── BrainCellAspect.java │ ├── cell │ │ ├── AbstractBrainCell.java │ │ ├── ApiBrainCell.java │ │ ├── BrainCell.java │ │ ├── CommonBrainCell.java │ │ ├── EmoticonBrainCell.java │ │ └── KnowledgeBrainCell.java │ └── factory │ │ └── BrainFactory.java │ ├── common │ ├── annotations │ │ ├── Brain.java │ │ └── BrainCell.java │ ├── enums │ │ ├── BrainRequestType.java │ │ ├── BrainResponseType.java │ │ └── GrantType.java │ ├── exception │ │ ├── ArgumentInvalidException.java │ │ ├── BrainException.java │ │ └── InvalidReturnTypeException.java │ ├── interfaces │ │ ├── Dispatcher.java │ │ └── MemberService.java │ ├── properties │ │ └── BotProperties.java │ ├── request │ │ └── BrainRequest.java │ ├── result │ │ ├── BrainCellResult.java │ │ ├── BrainResult.java │ │ └── CommonResult.java │ └── util │ │ ├── BrainUtil.java │ │ └── RestTemplateFactory.java │ ├── conversation │ ├── Conversation.java │ └── ConversationService.java │ ├── event │ ├── Event.java │ ├── EventQueue.java │ └── TaskRunner.java │ └── messenger │ └── teamup │ ├── Api.java │ ├── TeamUpDispatcher.java │ ├── TeamUpEventSensor.java │ ├── TeamUpMemberCached.java │ ├── TeamUpMemberService.java │ ├── TeamUpTokenManager.java │ ├── message │ └── MessageService.java │ ├── oauth2 │ └── OAuth2Token.java │ ├── request │ ├── FileRequest.java │ ├── MessageRequest.java │ └── RoomCreateRequest.java │ ├── response │ ├── EventResponse.java │ ├── FeedGroupsResponse.java │ ├── FileUploadResponse.java │ ├── MessageResponse.java │ ├── OrganigrammeResponse.java │ ├── RefreshResponse.java │ ├── RoomCreateResponse.java │ └── RoomInfoResponse.java │ ├── templates │ ├── BaseTemplate.java │ └── template │ │ ├── AuthTemplate.java │ │ ├── EdgeTemplate.java │ │ ├── EventTemplate.java │ │ ├── FileTemplate.java │ │ └── Oauth2Template.java │ └── util │ └── ImagesUtils.java └── resources └── META-INF └── spring.factories /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | nbbuild/ 23 | dist/ 24 | nbdist/ 25 | .nb-gradle/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | @Deprecated https://github.com/ultzum/spring-boot-starter-chatbot 2 | 3 | https://github.com/kingbbode/spring-boot-chatbot 로 이전 4 | 5 | # Kingbbode Chat Bot Framework 6 | 7 | *최초 작성일 : 2017-02-07* 8 | 9 | *Document 는 최하단 작성* 10 | 11 | ## 왜 개발하는가? 12 | 13 | - 만들고 있는 Chat Bot을 알아가고 있는 지식을 적용한 리펙토링 및 라이브러리화 하고 싶어서 14 | - 챗봇 개발의 진입 장벽을 낮춰주기 위해서 15 | - 메신저 상관없는 통합 Chat Bot은 반드시 필요할 것 같아서 16 | 17 | ## 기반 기술은? 18 | 19 | - Spring Framework 위에서 만드는 프레임워크?(프레임워크 in 프레임워크?);는 아니고 그냥 Spring Framework 쓴 개발임. 20 | - Java Reflection과 Spring AOP를 활발히 사용 21 | - Generic과 Interface를 통한 다형성 22 | - Java8 적극 활용 23 | 24 | ## 컨셉 25 | 26 | - 봇의 뇌와 뇌세포라는 의미로, 구현체 객체를 `Brain` , 구현체 객체 내부에 하나의 명령어와 Mapping되는 기능을 `BrainCell` 이라고 컨셉을 잡음. 27 | - Annotaion 기반의 구현체 개발(Spring의 Controller를 모방, @Conroller - @Brain, @RequestMapping - @BrainCell) 28 | - 모든 요청과 반환을 담당하는 `DispatcherBrain` 29 | - 모든 Brain의 생성 및 반환 역할을 하는 `BrainFactory` 30 | 31 | ## 현재 상태는? 32 | 33 | - 기능과 패키지 등의 분리는 어느정도 완료. 34 | - 모듈화를 한다고 했지만, 코드가 굉장히 지저분하여 리펙토링이 시급함(그래서 테스트코드가 더 시급함). 35 | - 기능 및 동작에 대한 분리는 완료. 36 | - 마지막 커밋으로 챗봇 Service 구현부, 챗봇 코어, 챗봇 메신저 라이브러리를 분리 완료. 37 | - 나름 Spring Boot Starter 만들었으나, 잘 모르고 만들어서 지저분함. 38 | 39 | ## 앞으로 계획 40 | 41 | - 테스트 케이스 작성..(TDD....가 뭔지도 몰랐던 시절부터 작성되어 이제는 테스트 붙이는게 일이..) 42 | - 카카오, 슬랙, 텔레그램 등의 메신저 라이브러리 확장. 43 | - 메신저 라이브러리가 확장된다면 각각의 sub starter로 다시 분리. 44 | 45 | ## 활용 46 | 47 | 거의 노는 용.. 48 | 49 | ### 회의실 조회 기능 50 | 51 | ![회의실!](./images/cf.png) 52 | 53 | ### 이모티콘 기능 54 | 55 | ![이모티콘!](./images/cf2.png) 56 | 57 | ### 학습 58 | 59 | ![학습!](./images/cf3.png) 60 | 61 | ### 등등 하여 2017-07-10 현재 62 | 63 | ![현재!](./images/cf4.png) 64 | 65 | --- 66 | 67 | ## Document 68 | 69 | ### application.properties 70 | 71 | ```java 72 | # CHAT-BOT 73 | chatbot.name = default 74 | chatbot.basePackage = com.kingbbode.example 75 | chatbot.enabled = true 76 | chatbot.enableBase = true 77 | chatbot.enableEmoticon = true 78 | chatbot.enableKnowledge = true 79 | # Redis 80 | chatbot.hostName = localhost 81 | chatbot.port = 6879 82 | chatbot.timeout = 0 83 | chatbot.password = {password} 84 | chatbot.usePool = true 85 | chatbot.useSsl = false 86 | chatbot.dbIndex = 0 87 | chatbot.clientName = {clientName} 88 | chatbot.convertPipelineAndTxResults = true 89 | # Command 90 | chatbot.commandPrefix = # 91 | chatbot.emoticonPrefix = @ 92 | 93 | # TEAMUP 94 | chatbot.teamup.enabled = true 95 | chatbot.teamup.id = {아이디} 96 | chatbot.teamup.password = {비밀번호} 97 | chatbot.teamup.clientId = {clientId} 98 | chatbot.teamup.clientSecret = {clientSecret} 99 | chatbot.teamup.testRoom = {DEV 모드 테스트 방 번호} 100 | chatbot.teamup.testFeed = {DEV 모드 테스트 피드 번호} 101 | chatbot.teamup.bot[0] = {bot user id} 102 | .. 103 | chatbot.teamup.bot[n] = {bot user id} 104 | ``` 105 | 106 | **Core** 107 | 108 | - chatbot.name : chatbot 이름(redis key의 prefix가 됨) 109 | - chatbot.basePackage : Root Package 를 지정 - default "" 110 | - chatbot.enabled : {true or false} 챗봇 사용 여부 - default false 111 | - chatbot.enableBase = {true or false} Base Brain 사용 여부(base Brain 에는 기능 목록을 출력하는 기능이 작성되어 있음) - default true 112 | - chatbot.enableEmoticon = {true or false} Emoticon Brain 사용 여부(emoticon Brain 에는 @를 prefix로 받아 이모티콘을 처리하기 위한 기능이 작성되어 있음, 이모티콘을 저장하는 형태는 구현 프로젝트에서 작성해야 함) - default false 113 | - chatbot.enableKnowledge = {true or false} Knowledge Brain 사용 여부( knowledge Brain 에는 학습 기능이 작성되어 있음) - default false 114 | - chatbot.commandPrefix = 명령어의 접두어 115 | - chatbot.emoticonPrefix = 이모티콘 접두어 116 | 117 | **Redis** 118 | 119 | 대화형(이전 대화와 연결되는 형태)을 완성시키기 위해 대화 상태를 저장하는 저장소를 `REDIS` 로 사용. 120 | 121 | - chatbot.hostName : - default "localhost" 122 | - chatbot.port : - default 6379 123 | - chatbot.timeout : - default 2000 124 | - chatbot.password : - default null 125 | - chatbot.usePool : - default true 126 | - chatbot.useSsl : - default false 127 | - chatbot.dbIndex : - default 0 128 | - chatbot.clientName : - default null 129 | - chatbot.convertPipelineAndTxResults : - default true 130 | 131 | **메신저 TEAMUP** 132 | 133 | - chatbot.teamup.enabled = {true or false} (사용 여부) 134 | - chatbot.teamup.id = {아이디} 135 | - chatbot.teamup.password = {비밀번호} 136 | - chatbot.teamup.clientId = {clientId} 137 | - chatbot.teamup.clientSecret = {clientSecret} 138 | - chatbot.teamup.testRoom = {DEV 모드 테스트 방 번호} 139 | - chatbot.teamup.testFeed = {DEV 모드 테스트 피드 번호} 140 | - chatbot.teamup.bot[0-N] = {메시지를 무시할 대상} 141 | 142 | ### Example Project 143 | 144 | [Spring Boot Starter Chatbot Example](https://github.com/kingbbode/spring-boot-starter-chatbot-example) 145 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext { 3 | springBootVersion = '1.5.4.RELEASE' 4 | } 5 | repositories { 6 | mavenCentral() 7 | } 8 | dependencies { 9 | classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") 10 | } 11 | } 12 | 13 | apply plugin: 'java' 14 | apply plugin: 'eclipse' 15 | apply plugin: 'org.springframework.boot' 16 | 17 | group = 'com.kingbbode' 18 | version = '1.0.3-SNAPSHOT' 19 | sourceCompatibility = 1.8 20 | 21 | repositories { 22 | mavenCentral() 23 | } 24 | 25 | 26 | dependencies { 27 | compile('org.springframework.boot:spring-boot-starter-web') 28 | compile('org.springframework.boot:spring-boot-starter-aop') 29 | compile("org.springframework.boot:spring-boot-starter-data-redis") 30 | compile('org.apache.commons:commons-lang3:3.1') 31 | compile('org.reflections:reflections:0.9.10') 32 | compile('joda-time:joda-time:2.9.3') 33 | compile("com.fasterxml.jackson.datatype:jackson-datatype-joda:2.4.0") 34 | compileOnly("org.projectlombok:lombok:1.16.16") 35 | compile("org.apache.httpcomponents:httpclient:4.5.3") 36 | testCompile('org.springframework.boot:spring-boot-starter-test') 37 | } 38 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ultzum/spring-boot-starter-chatbot/384cafd09fc3b89b18dfe3c4b55b2c7286ab631e/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.5.1-bin.zip 6 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn ( ) { 37 | echo "$*" 38 | } 39 | 40 | die ( ) { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save ( ) { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /images/cf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ultzum/spring-boot-starter-chatbot/384cafd09fc3b89b18dfe3c4b55b2c7286ab631e/images/cf.png -------------------------------------------------------------------------------- /images/cf2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ultzum/spring-boot-starter-chatbot/384cafd09fc3b89b18dfe3c4b55b2c7286ab631e/images/cf2.png -------------------------------------------------------------------------------- /images/cf3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ultzum/spring-boot-starter-chatbot/384cafd09fc3b89b18dfe3c4b55b2c7286ab631e/images/cf3.png -------------------------------------------------------------------------------- /images/cf4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ultzum/spring-boot-starter-chatbot/384cafd09fc3b89b18dfe3c4b55b2c7286ab631e/images/cf4.png -------------------------------------------------------------------------------- /out/production/spring-boot-starter-chatbot/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | # Auto Configure 2 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ 3 | com.kingbbode.chatbot.autoconfigure.ChatbotAutoConfiguration -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/ChatbotAutoConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure; 2 | 3 | import com.kingbbode.chatbot.autoconfigure.base.BaseBrain; 4 | import com.kingbbode.chatbot.autoconfigure.base.emoticon.brain.EmoticonBrain; 5 | import com.kingbbode.chatbot.autoconfigure.base.emoticon.component.EmoticonComponent; 6 | import com.kingbbode.chatbot.autoconfigure.base.knowledge.brain.KnowledgeBrain; 7 | import com.kingbbode.chatbot.autoconfigure.base.knowledge.component.KnowledgeComponent; 8 | import com.kingbbode.chatbot.autoconfigure.base.stat.StatComponent; 9 | import com.kingbbode.chatbot.autoconfigure.brain.DispatcherBrain; 10 | import com.kingbbode.chatbot.autoconfigure.brain.aop.BrainCellAspect; 11 | import com.kingbbode.chatbot.autoconfigure.brain.factory.BrainFactory; 12 | import com.kingbbode.chatbot.autoconfigure.common.properties.BotProperties; 13 | import com.kingbbode.chatbot.autoconfigure.common.util.RestTemplateFactory; 14 | import com.kingbbode.chatbot.autoconfigure.conversation.ConversationService; 15 | import com.kingbbode.chatbot.autoconfigure.event.EventQueue; 16 | import com.kingbbode.chatbot.autoconfigure.event.TaskRunner; 17 | import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; 18 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 19 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 20 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 21 | import org.springframework.context.annotation.Bean; 22 | import org.springframework.context.annotation.Configuration; 23 | import org.springframework.context.annotation.Import; 24 | import org.springframework.context.annotation.Profile; 25 | import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; 26 | import org.springframework.data.redis.core.StringRedisTemplate; 27 | import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; 28 | import org.springframework.http.converter.ByteArrayHttpMessageConverter; 29 | import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; 30 | import org.springframework.web.client.RestOperations; 31 | import org.springframework.web.client.RestTemplate; 32 | 33 | import static com.kingbbode.chatbot.autoconfigure.common.util.RestTemplateFactory.getRestOperations; 34 | 35 | /** 36 | * Created by YG on 2017-07-10. 37 | */ 38 | @Configuration 39 | @ConditionalOnProperty(prefix = "chatbot", name = "enabled", havingValue = "true") 40 | @EnableConfigurationProperties(ChatbotProperties.class) 41 | @Import(TeamUpAutoConfiguration.class) 42 | public class ChatbotAutoConfiguration { 43 | 44 | private ChatbotProperties chatbotProperties; 45 | 46 | public ChatbotAutoConfiguration(ChatbotProperties chatbotProperties) { 47 | this.chatbotProperties = chatbotProperties; 48 | } 49 | 50 | @Bean 51 | @ConditionalOnMissingBean 52 | public BrainFactory brainFactory(){ 53 | return new BrainFactory(); 54 | } 55 | 56 | @Bean 57 | @ConditionalOnMissingBean 58 | public EventQueue eventQueue(){ 59 | return new EventQueue(); 60 | } 61 | 62 | @Bean 63 | @ConditionalOnMissingBean 64 | public JedisConnectionFactory jedisConnectionFactory() { 65 | JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(); 66 | jedisConnectionFactory.setHostName(chatbotProperties.getHostName()); 67 | jedisConnectionFactory.setPort(chatbotProperties.getPort()); 68 | jedisConnectionFactory.setTimeout(chatbotProperties.getTimeout()); 69 | jedisConnectionFactory.setPassword(chatbotProperties.getPassword()); 70 | jedisConnectionFactory.setUsePool(chatbotProperties.isUsePool()); 71 | jedisConnectionFactory.setUseSsl(chatbotProperties.isUseSsl()); 72 | jedisConnectionFactory.setDatabase(chatbotProperties.getDbIndex()); 73 | jedisConnectionFactory.setClientName(chatbotProperties.getClientName()); 74 | jedisConnectionFactory.setConvertPipelineAndTxResults(chatbotProperties.isConvertPipelineAndTxResults()); 75 | 76 | return jedisConnectionFactory; 77 | } 78 | 79 | @Bean 80 | @ConditionalOnMissingBean 81 | public StringRedisTemplate redisTemplate(JedisConnectionFactory jedisConnectionFactory) { 82 | StringRedisTemplate stringRedisTemplate = new StringRedisTemplate(); 83 | stringRedisTemplate.setConnectionFactory(jedisConnectionFactory); 84 | return stringRedisTemplate; 85 | } 86 | 87 | @Bean 88 | @ConditionalOnMissingBean 89 | public ConversationService conversationService(){ 90 | return new ConversationService(); 91 | } 92 | 93 | @Bean(name = "messageRestOperations") 94 | public RestOperations messageRestOperations() { 95 | HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(); 96 | factory.setConnectTimeout(1000); 97 | factory.setReadTimeout(1000); 98 | return getRestOperations(factory); 99 | } 100 | 101 | @Bean(name = "fileRestOperations") 102 | public RestOperations fileRestOperations() { 103 | HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(); 104 | factory.setConnectTimeout(20000); 105 | factory.setReadTimeout(20000); 106 | RestTemplate restTemplate = (RestTemplate) RestTemplateFactory.getRestOperations(factory); 107 | restTemplate.getMessageConverters().add(new ByteArrayHttpMessageConverter()); 108 | return restTemplate; 109 | } 110 | 111 | @Bean(name = "eventRestOperations") 112 | public RestOperations eventRestOperations() { 113 | HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(); 114 | factory.setConnectTimeout(30000); 115 | factory.setReadTimeout(30000); 116 | return getRestOperations(factory); 117 | } 118 | 119 | @Bean(name = "eventQueueTreadPool") 120 | public ThreadPoolTaskExecutor eventQueueTreadPool() { 121 | ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); 122 | executor.setCorePoolSize(5); 123 | executor.setMaxPoolSize(10); 124 | executor.setQueueCapacity(1000); 125 | executor.setWaitForTasksToCompleteOnShutdown(true); 126 | return executor; 127 | } 128 | 129 | @Bean 130 | @ConditionalOnMissingBean 131 | public TaskRunner taskRunner(){ 132 | return new TaskRunner(); 133 | } 134 | 135 | @Bean 136 | @ConditionalOnMissingBean 137 | @ConditionalOnProperty(prefix = "chatbot", name = "enableBase", havingValue = "true") 138 | public BaseBrain baseBrain(){ 139 | return new BaseBrain(); 140 | } 141 | 142 | @Bean 143 | @ConditionalOnMissingBean 144 | @ConditionalOnProperty(prefix = "chatbot", name = "enableEmoticon", havingValue = "true") 145 | public EmoticonBrain emoticonBrain(){ 146 | return new EmoticonBrain(); 147 | } 148 | 149 | @Bean 150 | @ConditionalOnMissingBean 151 | @ConditionalOnProperty(prefix = "chatbot", name = "enableEmoticon", havingValue = "true") 152 | public EmoticonComponent emoticonComponent(){ 153 | return new EmoticonComponent(); 154 | } 155 | 156 | @Bean 157 | @ConditionalOnMissingBean 158 | @ConditionalOnProperty(prefix = "chatbot", name = "enableKnowledge", havingValue = "true") 159 | public KnowledgeBrain knowledgeBrain(){ 160 | return new KnowledgeBrain(); 161 | } 162 | 163 | @Bean 164 | @ConditionalOnMissingBean 165 | @ConditionalOnProperty(prefix = "chatbot", name = "enableKnowledge", havingValue = "true") 166 | public KnowledgeComponent knowledgeComponent(){ 167 | return new KnowledgeComponent(); 168 | } 169 | 170 | @Bean 171 | @ConditionalOnMissingBean 172 | public StatComponent statComponent(){ 173 | return new StatComponent(); 174 | } 175 | 176 | @Bean 177 | @Profile({"bot"}) 178 | public BotProperties realBotConfig(){ 179 | return new BotProperties(chatbotProperties.getName(), chatbotProperties.getCommandPrefix(), chatbotProperties.getEmoticonPrefix(), false); 180 | } 181 | 182 | @Bean 183 | @Profile({"dev"}) 184 | public BotProperties devBotConfig(){ 185 | return new BotProperties(chatbotProperties.getName(),"#" + chatbotProperties.getCommandPrefix(), chatbotProperties.getEmoticonPrefix(), true); 186 | } 187 | 188 | @Bean 189 | @ConditionalOnMissingBean 190 | public DispatcherBrain dispatcherBrain(){ 191 | return new DispatcherBrain(); 192 | } 193 | 194 | @Bean 195 | @ConditionalOnMissingBean 196 | public BrainCellAspect brainCellAspect(){ 197 | return new BrainCellAspect(); 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/ChatbotProperties.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | 5 | import lombok.Data; 6 | import redis.clients.jedis.Protocol; 7 | 8 | /** 9 | * Created by YG on 2017-07-10. 10 | */ 11 | @ConfigurationProperties(prefix = "chatbot") 12 | @Data 13 | public class ChatbotProperties { 14 | private String name = "default"; 15 | private String basePackage = ""; 16 | private boolean enableBase = true; 17 | private boolean enableEmoticon = false; 18 | private boolean enableKnowledge = false; 19 | 20 | private String hostName = "localhost"; 21 | private int port = Protocol.DEFAULT_PORT; 22 | private int timeout = Protocol.DEFAULT_TIMEOUT; 23 | private String password; 24 | private boolean usePool = true; 25 | private boolean useSsl = false; 26 | private int dbIndex = 0; 27 | private String clientName; 28 | private boolean convertPipelineAndTxResults = true; 29 | 30 | private String commandPrefix = "#"; 31 | private String emoticonPrefix = "@"; 32 | } 33 | 34 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/TeamUpAutoConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure; 2 | 3 | import com.kingbbode.chatbot.autoconfigure.common.interfaces.MemberService; 4 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.*; 5 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.message.MessageService; 6 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.templates.template.*; 7 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 8 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 9 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 10 | import org.springframework.context.annotation.Bean; 11 | import org.springframework.context.annotation.Configuration; 12 | 13 | /** 14 | * Created by YG on 2017-07-10. 15 | */ 16 | @Configuration 17 | @ConditionalOnProperty(prefix = "chatbot.teamup", name = "enabled", havingValue = "true") 18 | @EnableConfigurationProperties({TeamUpProperties.class}) 19 | public class TeamUpAutoConfiguration { 20 | 21 | @Bean 22 | @ConditionalOnMissingBean 23 | public TeamUpEventSensor teamUpEventSensor(){ 24 | return new TeamUpEventSensor(); 25 | } 26 | 27 | @Bean 28 | @ConditionalOnMissingBean 29 | public TeamUpTokenManager teamUpTokenManager(){ 30 | return new TeamUpTokenManager(); 31 | } 32 | 33 | @Bean 34 | @ConditionalOnMissingBean 35 | public TeamUpDispatcher teamUpDispatcher(){ 36 | return new TeamUpDispatcher(); 37 | } 38 | 39 | @Bean 40 | @ConditionalOnMissingBean 41 | public MessageService messageService(){ 42 | return new MessageService(); 43 | } 44 | 45 | @Bean 46 | @ConditionalOnMissingBean 47 | public Oauth2Template oauth2Template(){ 48 | return new Oauth2Template(); 49 | } 50 | 51 | @Bean 52 | @ConditionalOnMissingBean 53 | public AuthTemplate authTemplate(){ 54 | return new AuthTemplate(); 55 | } 56 | 57 | @Bean 58 | @ConditionalOnMissingBean 59 | public EdgeTemplate edgeTemplate(){ 60 | return new EdgeTemplate(); 61 | } 62 | 63 | @Bean 64 | @ConditionalOnMissingBean 65 | public EventTemplate eventTemplate(){ 66 | return new EventTemplate(); 67 | } 68 | 69 | @Bean 70 | @ConditionalOnMissingBean 71 | public FileTemplate fileTemplate(){ 72 | return new FileTemplate(); 73 | } 74 | 75 | @Bean 76 | @ConditionalOnMissingBean 77 | public TeamUpMemberCached teamUpMemberCached(){ 78 | return new TeamUpMemberCached(); 79 | } 80 | 81 | @Bean(name = "teamUpMemberService") 82 | @ConditionalOnMissingBean 83 | public MemberService teamUpMemberService(){ 84 | return new TeamUpMemberService(); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/TeamUpProperties.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import org.springframework.boot.context.properties.ConfigurationProperties; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * Created by YG on 2017-07-10. 11 | */ 12 | @ConfigurationProperties(prefix = "chatbot.teamup") 13 | @Getter 14 | @Setter 15 | public class TeamUpProperties { 16 | private String id; 17 | private String password; 18 | private String clientId; 19 | private String clientSecret; 20 | private String testRoom; 21 | private String testFeed; 22 | private String testUser; 23 | private List bot; 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/api/AbstractBotApi.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.api; 2 | 3 | 4 | import com.kingbbode.chatbot.autoconfigure.common.request.BrainRequest; 5 | import com.kingbbode.chatbot.autoconfigure.common.result.BrainResult; 6 | 7 | /** 8 | * Created by YG on 2017-01-26. 9 | */ 10 | public abstract class AbstractBotApi implements BotApi { 11 | 12 | public BrainResult execute(BrainRequest brainRequest) { 13 | T api = getRequest(brainRequest.getContent()); 14 | 15 | return BrainResult.builder() 16 | .room(brainRequest.getRoom()) 17 | .result(get(api)) 18 | .type(api.response()) 19 | .build(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/api/ApiData.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.api; 2 | 3 | 4 | import com.kingbbode.chatbot.autoconfigure.common.enums.BrainResponseType; 5 | 6 | /** 7 | * Created by YG on 2017-01-26. 8 | */ 9 | public interface ApiData { 10 | BrainResponseType response(); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/api/BotApi.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.api; 2 | 3 | 4 | import com.kingbbode.chatbot.autoconfigure.common.result.BrainCellResult; 5 | 6 | import java.util.Collection; 7 | 8 | /** 9 | * Created by YG on 2017-01-26. 10 | */ 11 | public interface BotApi { 12 | void update(); 13 | 14 | BrainCellResult get(T request); 15 | 16 | T getRequest(String command); 17 | 18 | Collection getCommands(); 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/base/BaseBrain.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.base; 2 | 3 | import com.kingbbode.chatbot.autoconfigure.base.emoticon.component.EmoticonComponent; 4 | import com.kingbbode.chatbot.autoconfigure.base.knowledge.component.KnowledgeComponent; 5 | import com.kingbbode.chatbot.autoconfigure.base.stat.StatComponent; 6 | import com.kingbbode.chatbot.autoconfigure.brain.cell.ApiBrainCell; 7 | import com.kingbbode.chatbot.autoconfigure.brain.cell.CommonBrainCell; 8 | import com.kingbbode.chatbot.autoconfigure.brain.factory.BrainFactory; 9 | import com.kingbbode.chatbot.autoconfigure.common.annotations.Brain; 10 | import com.kingbbode.chatbot.autoconfigure.common.annotations.BrainCell; 11 | import com.kingbbode.chatbot.autoconfigure.common.enums.BrainResponseType; 12 | import com.kingbbode.chatbot.autoconfigure.common.request.BrainRequest; 13 | import com.kingbbode.chatbot.autoconfigure.common.util.BrainUtil; 14 | import org.springframework.beans.factory.annotation.Autowired; 15 | 16 | /** 17 | * Created by YG-MAC on 2017. 1. 27.. 18 | */ 19 | @Brain 20 | public class BaseBrain { 21 | 22 | @Autowired 23 | private BrainFactory brainFactory; 24 | 25 | @Autowired 26 | private KnowledgeComponent knowledgeComponent; 27 | 28 | @Autowired 29 | private EmoticonComponent emoticonComponent; 30 | 31 | @Autowired 32 | private StatComponent statComponent; 33 | 34 | @BrainCell(key = "기능", explain = "기능 목록 출력", function = "function") 35 | public String explain(BrainRequest brainRequest) { 36 | return "**** 기능 목록 **** \n" + 37 | BrainUtil.explainDetail(brainFactory.findBrainCellByType(CommonBrainCell.class)) + 38 | "\n**** API 기능 목록 **** \n" + 39 | BrainUtil.explainDetail(brainFactory.findBrainCellByType(ApiBrainCell.class)) + 40 | "\n**** 이모티콘 목록 **** \n" + 41 | BrainUtil.explainForEmoticon(emoticonComponent.getEmoticons()) + 42 | "\n**** 학습 목록 **** \n" + 43 | BrainUtil.explainForKnowledge(knowledgeComponent.getCommands()); 44 | } 45 | 46 | @BrainCell(key = "고유정보", explain = "고유 정보 추출",function = "teamup") 47 | public String teamupId(BrainRequest brainRequest){ 48 | return brainRequest.toString(); 49 | } 50 | 51 | @BrainCell(key = "나가", explain = "쫓아내기", function = "getout", type = BrainResponseType.OUT) 52 | public String outRoom(BrainRequest brainRequest) { 53 | return "바이바이~"; 54 | } 55 | 56 | @BrainCell(key = "기능통계", explain = "뭘 많이 쓰는지..", function = "statstat") 57 | public String getStat(BrainRequest brainRequest) { 58 | return statComponent.toString(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/base/emoticon/brain/EmoticonBrain.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.base.emoticon.brain; 2 | 3 | import com.kingbbode.chatbot.autoconfigure.base.emoticon.component.EmoticonComponent; 4 | import com.kingbbode.chatbot.autoconfigure.common.annotations.Brain; 5 | import com.kingbbode.chatbot.autoconfigure.common.annotations.BrainCell; 6 | import com.kingbbode.chatbot.autoconfigure.common.exception.BrainException; 7 | import com.kingbbode.chatbot.autoconfigure.common.request.BrainRequest; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; 10 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 11 | 12 | import java.util.Set; 13 | 14 | /** 15 | * Created by YG on 2017-04-07. 16 | */ 17 | @Brain 18 | @ConditionalOnBean(EmoticonComponent.class) 19 | @ConditionalOnProperty(prefix = "chatbot", name = "enableEmoticon", havingValue = "true") 20 | public class EmoticonBrain { 21 | 22 | @Autowired 23 | private EmoticonComponent emoticonComponent; 24 | 25 | @BrainCell(key = "이모티콘", explain = "이모티콘 조회 및 등록", function = "emoticon") 26 | public String emoticon(BrainRequest brainRequest){ 27 | return "조회하려면 '조회'\n" + 28 | "등록하려면 '등록'\n" + 29 | "삭제하려면 '삭제'\n" + 30 | "을 입력해주세요."; 31 | } 32 | 33 | @BrainCell(parent = "emoticon", key = "조회", function = "emoticonList") 34 | public String emoticonList(BrainRequest brainRequest){ 35 | Set emoticonEntrySet = emoticonComponent.getEmoticons().keySet(); 36 | if(emoticonEntrySet.size()>0){ 37 | StringBuilder result = new StringBuilder(); 38 | result 39 | .append("총 ") 40 | .append(emoticonEntrySet.size()) 41 | .append("개\n"); 42 | 43 | for (String key : emoticonEntrySet) { 44 | result 45 | .append(key) 46 | .append("\n"); 47 | } 48 | return result.toString(); 49 | }else{ 50 | return "등록된 이모티콘이 업습니다"; 51 | } 52 | } 53 | 54 | @BrainCell(parent = "emoticon", key = "등록", function = "emoticonReg0") 55 | public String emoticonReg(BrainRequest brainRequest){ 56 | return "등록할 명령어를 입력해주세요."; 57 | } 58 | 59 | @BrainCell(parent = "emoticonReg0", function = "emoticonReg1") 60 | public String emoticonReg1(BrainRequest brainRequest){ 61 | if(emoticonComponent.contains(brainRequest.getContent())){ 62 | throw new BrainException(null, "이미 등록된 이름입니다. 다시 입력해주세요."); 63 | } 64 | brainRequest.getConversation().put("name", brainRequest.getContent()); 65 | return "등록할 이미지를 전송해주세요.\n" + 66 | "jpg나 png만 허용합니다.\n" + 67 | "파일이름에 공백 또는 . 을 허용하지 않습니다."; 68 | } 69 | 70 | @BrainCell(parent = "emoticonReg1", function = "emoticonReg2") 71 | public String emoticonReg2(BrainRequest brainRequest){ 72 | throw new BrainException(null, "등록할 이미지를 전송해주세요."); 73 | } 74 | 75 | @BrainCell(parent = "emoticon", key = "삭제", function = "emoticonDelete") 76 | public String emoticonDelete(BrainRequest brainRequest){ 77 | return "삭제할 명령어를 입력해주세요."; 78 | } 79 | 80 | @BrainCell(parent = "emoticonDelete", function = "emoticonDelete1") 81 | public String emoticonDelete1(BrainRequest brainRequest){ 82 | if(!emoticonComponent.contains(brainRequest.getContent())){ 83 | throw new BrainException(null, "등록되지 않은 이모티콘입니다. 다시 입력해주세요."); 84 | } 85 | emoticonComponent.remove(brainRequest.getContent()); 86 | return brainRequest.getContent() + " 이모티콘이 삭제되었습니다."; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/base/emoticon/component/EmoticonComponent.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.base.emoticon.component; 2 | 3 | import com.kingbbode.chatbot.autoconfigure.base.stat.StatComponent; 4 | import com.kingbbode.chatbot.autoconfigure.common.properties.BotProperties; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.data.redis.core.HashOperations; 7 | 8 | import javax.annotation.PostConstruct; 9 | import javax.annotation.Resource; 10 | import java.io.IOException; 11 | import java.util.Map; 12 | import java.util.concurrent.ConcurrentHashMap; 13 | 14 | /** 15 | * Created by YG on 2016-11-01. 16 | */ 17 | public class EmoticonComponent { 18 | 19 | @Resource(name="redisTemplate") 20 | private HashOperations hashOperations; 21 | 22 | @Autowired 23 | private StatComponent statComponent; 24 | 25 | @Autowired 26 | private BotProperties botProperties; 27 | 28 | private static final String REDIS_KEY_EMOTICON = ":emoticon"; 29 | 30 | private String key; 31 | private Map emoticons; 32 | 33 | @PostConstruct 34 | public void init() { 35 | this.key = botProperties.getName() + REDIS_KEY_EMOTICON; 36 | Map map = new ConcurrentHashMap<>(); 37 | Map entries = hashOperations.entries(this.key); 38 | for(Map.Entry entry : entries.entrySet()){ 39 | map.put(entry.getKey(), entry.getValue()); 40 | } 41 | emoticons = map; 42 | } 43 | 44 | public String get(String content){ 45 | String candi = emoticons.getOrDefault(content, null); 46 | if(candi != null){ 47 | statComponent.plus("이모티콘:" + content); 48 | } 49 | return candi; 50 | } 51 | 52 | public Map getEmoticons(){ 53 | return emoticons; 54 | } 55 | 56 | public void put(String key, String value){ 57 | hashOperations.put(this.key, botProperties.getEmoticonPrefix() + key, value); 58 | emoticons.put(botProperties.getEmoticonPrefix() + key, value); 59 | } 60 | 61 | public boolean contains(String key){ 62 | return emoticons.containsKey(botProperties.getEmoticonPrefix() + key); 63 | } 64 | 65 | public void remove(String key) { 66 | hashOperations.delete(this.key, botProperties.getEmoticonPrefix() + key); 67 | emoticons.remove(botProperties.getEmoticonPrefix() + key); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/base/knowledge/brain/KnowledgeBrain.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.base.knowledge.brain; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import com.kingbbode.chatbot.autoconfigure.base.knowledge.component.KnowledgeComponent; 5 | import com.kingbbode.chatbot.autoconfigure.common.annotations.Brain; 6 | import com.kingbbode.chatbot.autoconfigure.common.annotations.BrainCell; 7 | import com.kingbbode.chatbot.autoconfigure.common.exception.ArgumentInvalidException; 8 | import com.kingbbode.chatbot.autoconfigure.common.request.BrainRequest; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; 13 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 14 | 15 | /** 16 | * Created by YG-MAC on 2017. 1. 26.. 17 | */ 18 | @Brain 19 | @ConditionalOnBean(KnowledgeComponent.class) 20 | @ConditionalOnProperty(prefix = "chatbot", name = "enableKnowledge", havingValue = "true") 21 | public class KnowledgeBrain { 22 | 23 | @Autowired 24 | private KnowledgeComponent knowledgeComponent; 25 | 26 | private final Logger logger = LoggerFactory.getLogger(this.getClass()); 27 | 28 | @BrainCell(key = "학습", explain = "명령어 학습시키기", function = "addKnowledge") 29 | public String addKnowledge(BrainRequest brainRequest) throws JsonProcessingException { 30 | return "학습시킬 명령어가 무엇인가요?"; 31 | } 32 | 33 | @BrainCell(parent = "addKnowledge", function = "addKnowledge2") 34 | public String addKnowledge2(BrainRequest brainRequest) { 35 | brainRequest.getConversation().put("key", brainRequest.getContent()); 36 | return "이 명렁어에 기억할 내용은 무엇인가요?"; 37 | } 38 | 39 | @BrainCell(parent = "addKnowledge2", function = "addKnowledge3", example = "입력하신 내용에 오류가 있습니다. 다시 입력해주세요.") 40 | public String addKnowledge3(BrainRequest brainRequest) { 41 | logger.info("addKnowledge user :{}, key : {}, content : {}", brainRequest.getUser(), brainRequest.getConversation().getParam().get("key"), brainRequest.getContent()); 42 | try { 43 | return knowledgeComponent.addKnowledge(brainRequest.getConversation().getParam().get("key"), brainRequest.getContent()); 44 | } catch (JsonProcessingException e) { 45 | throw new ArgumentInvalidException(e); 46 | } 47 | } 48 | 49 | @BrainCell(key = "까묵", explain = "학습 시킨 명령어 지우기", example = "까묵 명령어", function = "forgetKnowledge") 50 | public String forgetKnowledge(BrainRequest brainRequest) { 51 | return "무엇을 까먹을까요?"; 52 | } 53 | 54 | @BrainCell(parent = "forgetKnowledge", function = "forgetKnowledge2") 55 | public String forgetKnowledge2(BrainRequest brainRequest) { 56 | return knowledgeComponent.forgetKnowledge(brainRequest.getContent()); 57 | } 58 | } -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/base/knowledge/component/KnowledgeComponent.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.base.knowledge.component; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import com.fasterxml.jackson.core.type.TypeReference; 5 | import com.fasterxml.jackson.databind.ObjectMapper; 6 | import com.kingbbode.chatbot.autoconfigure.base.stat.StatComponent; 7 | import com.kingbbode.chatbot.autoconfigure.common.properties.BotProperties; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.data.redis.core.HashOperations; 10 | 11 | import javax.annotation.PostConstruct; 12 | import javax.annotation.Resource; 13 | import java.io.IOException; 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | import java.util.Map; 17 | import java.util.Set; 18 | import java.util.concurrent.ConcurrentHashMap; 19 | 20 | /** 21 | * Created by YG on 2016-04-12. 22 | */ 23 | public class KnowledgeComponent { 24 | 25 | @Resource(name="redisTemplate") 26 | private HashOperations hashOperations; 27 | 28 | @Autowired 29 | private ObjectMapper objectMapper; 30 | 31 | @Autowired 32 | private BotProperties botProperties; 33 | 34 | @Autowired 35 | private StatComponent statComponent; 36 | 37 | private static final String REDIS_KEY_KNOWLEDGE = ":knowledge"; 38 | 39 | private String key; 40 | private Map> knowledge; 41 | 42 | @PostConstruct 43 | public void init() throws IOException { 44 | this.key = botProperties.getName() + REDIS_KEY_KNOWLEDGE; 45 | Map> map = new ConcurrentHashMap<>(); 46 | Map entries = hashOperations.entries(this.key); 47 | for(Map.Entry entry : entries.entrySet()){ 48 | map.put(entry.getKey(), objectMapper.readValue(entry.getValue(), new TypeReference>() { 49 | })); 50 | } 51 | knowledge = map; 52 | } 53 | 54 | public void clear() { 55 | knowledge.clear(); 56 | } 57 | 58 | public boolean contains(String command){ 59 | return knowledge.containsKey(command); 60 | } 61 | 62 | public List get(String command) { 63 | List candi = knowledge.getOrDefault(command, null); 64 | if(candi != null){ 65 | statComponent.plus("학습:" + command); 66 | } 67 | return candi; 68 | } 69 | 70 | public String addKnowledge(String command, String content) throws JsonProcessingException { 71 | if (content.startsWith(botProperties.getCommandPrefix())) { 72 | return botProperties.getCommandPrefix() + "로 시작하는 내용은 암기할 수 없습니다"; 73 | } 74 | 75 | if (knowledge.containsKey(command)) { 76 | List list = knowledge.get(command); 77 | if (list.size() > 9) { 78 | return command + " 명령어에 습득할 수 있는 머리가 꽉 차서 못하겠습니다"; 79 | } 80 | list.add(content); 81 | hashOperations.put(this.key, command, objectMapper.writeValueAsString(list)); 82 | return command + " 명령어에 지식을 하나 더 습득했습니다"; 83 | } else { 84 | if (knowledge.size() > 10000) { 85 | return "제 머리로는 더 이상 지식을 습득할 수 없습니다"; 86 | } 87 | List list = new ArrayList<>(); 88 | list.add(content); 89 | knowledge.put(command, list); 90 | hashOperations.put(this.key, command, objectMapper.writeValueAsString(list)); 91 | return "새로운 지식을 습득했습니다. \n 사용법 : " + command; 92 | } 93 | } 94 | 95 | public String forgetKnowledge(String command) { 96 | if (knowledge.containsKey(command)) { 97 | knowledge.remove(command); 98 | hashOperations.delete(this.key, command); 99 | return command + "를 까먹었습니다"; 100 | } else { 101 | return "그런건 원래 모릅니다"; 102 | } 103 | } 104 | 105 | public Set>> getCommands(){ 106 | return knowledge.entrySet(); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/base/stat/StatComponent.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.base.stat; 2 | 3 | import org.springframework.stereotype.Component; 4 | 5 | import javax.annotation.PostConstruct; 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | /** 10 | * Created by YG on 2017-06-02. 11 | */ 12 | @Component 13 | public class StatComponent { 14 | private Map statMap; 15 | 16 | @PostConstruct 17 | public void init(){ 18 | statMap = new HashMap<>(); 19 | } 20 | 21 | public void plus(String key) { 22 | int current = 0; 23 | if(statMap.containsKey(key)){ 24 | current = statMap.get(key); 25 | } 26 | statMap.put(key, current + 1); 27 | } 28 | 29 | public String toString(){ 30 | StringBuilder stringBuilder = new StringBuilder(); 31 | statMap.entrySet().stream().sorted(Map.Entry.comparingByValue()).forEach(entry-> stringBuilder.append(entry.getKey()).append(":").append(entry.getValue()).append("\n")); 32 | return stringBuilder.toString(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/brain/DispatcherBrain.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.brain; 2 | 3 | import com.kingbbode.chatbot.autoconfigure.brain.cell.AbstractBrainCell; 4 | import com.kingbbode.chatbot.autoconfigure.brain.factory.BrainFactory; 5 | import com.kingbbode.chatbot.autoconfigure.common.enums.BrainResponseType; 6 | import com.kingbbode.chatbot.autoconfigure.common.request.BrainRequest; 7 | import com.kingbbode.chatbot.autoconfigure.common.result.BrainResult; 8 | import com.kingbbode.chatbot.autoconfigure.conversation.Conversation; 9 | import com.kingbbode.chatbot.autoconfigure.conversation.ConversationService; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | 14 | import java.io.IOException; 15 | import java.lang.reflect.InvocationTargetException; 16 | 17 | /** 18 | * Created by YG on 2017-01-23. 19 | */ 20 | public class DispatcherBrain { 21 | private static final Logger logger = LoggerFactory.getLogger(BrainFactory.class); 22 | 23 | @Autowired 24 | private BrainFactory brainFactory; 25 | 26 | @Autowired 27 | private ConversationService conversationService; 28 | 29 | public BrainResult execute(BrainRequest brainRequest) { 30 | try { 31 | return selectedBrainCell(brainRequest).execute(brainRequest); 32 | } catch (Exception e) { 33 | logger.warn("execute error -{}", e); 34 | } 35 | return null; 36 | } 37 | 38 | private T selectedBrainCell(BrainRequest brainRequest) throws IOException { 39 | Conversation conversation = conversationService.getLatest(brainRequest.getUser()); 40 | if(conversation != null && brainFactory.containsConversationInfo(conversation.getFunction())){ 41 | return conversation(brainRequest, conversation); 42 | } 43 | return brainFactory.get(brainRequest.getContent()); 44 | } 45 | 46 | @SuppressWarnings("unchecked") 47 | private T conversation(BrainRequest brainRequest, Conversation conversation) { 48 | BrainFactory.ConversationInfo info = brainFactory.getConversationInfo(conversation.getFunction()); 49 | String functionKey = info.findFunctionKey(brainRequest.getContent()); 50 | if(functionKey != null && brainFactory.containsFunctionKey(functionKey)){ 51 | brainRequest.setConversation(conversation); 52 | return brainFactory.getByFunctionKey(functionKey); 53 | } 54 | if(brainRequest.getContent().equals("취소")){ 55 | conversationService.delete(brainRequest.getUser()); 56 | return (T) new AbstractBrainCell(){ 57 | @Override 58 | public BrainResult execute(BrainRequest brainRequest) throws InvocationTargetException, IllegalAccessException { 59 | return BrainResult.builder() 60 | .message("취소되었습니다.") 61 | .room(brainRequest.getRoom()) 62 | .type(BrainResponseType.MESSAGE) 63 | .build(); 64 | } 65 | }; 66 | } 67 | return (T) new AbstractBrainCell(){ 68 | @Override 69 | public BrainResult execute(BrainRequest brainRequest) throws InvocationTargetException, IllegalAccessException { 70 | return BrainResult.builder() 71 | .message(info.example()) 72 | .room(brainRequest.getRoom()) 73 | .type(BrainResponseType.MESSAGE) 74 | .build(); 75 | } 76 | }; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/brain/aop/BrainCellAspect.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.brain.aop; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import com.kingbbode.chatbot.autoconfigure.base.stat.StatComponent; 5 | import com.kingbbode.chatbot.autoconfigure.brain.factory.BrainFactory; 6 | import com.kingbbode.chatbot.autoconfigure.common.annotations.BrainCell; 7 | import com.kingbbode.chatbot.autoconfigure.common.exception.InvalidReturnTypeException; 8 | import com.kingbbode.chatbot.autoconfigure.common.request.BrainRequest; 9 | import com.kingbbode.chatbot.autoconfigure.common.result.BrainCellResult; 10 | import com.kingbbode.chatbot.autoconfigure.conversation.Conversation; 11 | import com.kingbbode.chatbot.autoconfigure.conversation.ConversationService; 12 | import org.aspectj.lang.ProceedingJoinPoint; 13 | import org.aspectj.lang.annotation.Around; 14 | import org.aspectj.lang.annotation.Aspect; 15 | import org.aspectj.lang.reflect.MethodSignature; 16 | import org.slf4j.Logger; 17 | import org.slf4j.LoggerFactory; 18 | import org.springframework.beans.factory.annotation.Autowired; 19 | import org.springframework.util.ObjectUtils; 20 | 21 | /** 22 | * Created by YG-MAC on 2017. 1. 26.. 23 | */ 24 | @Aspect 25 | public class BrainCellAspect { 26 | 27 | private final Logger logger = LoggerFactory.getLogger(this.getClass()); 28 | 29 | @Autowired 30 | private ConversationService conversationService; 31 | 32 | @Autowired 33 | private BrainFactory brainFactory; 34 | 35 | @Autowired 36 | private StatComponent statComponent; 37 | 38 | @Around("@annotation(com.kingbbode.chatbot.autoconfigure.common.annotations.BrainCell)") 39 | public Object checkArgLength(ProceedingJoinPoint joinPoint) throws Throwable { 40 | BrainCell brainCell = ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(BrainCell.class); 41 | BrainRequest request = (BrainRequest) joinPoint.getArgs()[0]; 42 | if(!ObjectUtils.isEmpty(request.getConversation()) && brainCell.cancelable() && request.getContent().equals("취소")){ 43 | conversationService.delete(request.getUser()); 44 | return "초기화되었습니다."; 45 | } 46 | if(request.getContent().length() == 0){ 47 | return "입력해주세요."; 48 | } 49 | Object object = joinPoint.proceed(); 50 | 51 | if(!(object instanceof String) && !(object instanceof BrainCellResult) ){ 52 | throw new InvalidReturnTypeException(new Throwable()); 53 | } 54 | 55 | conversation(brainCell, request); 56 | 57 | if("".equals(brainCell.parent())){ 58 | statComponent.plus(brainCell.key()); 59 | } 60 | 61 | return conversationComment(object, brainCell); 62 | } 63 | 64 | private Object conversationComment(Object object, BrainCell brainCell) { 65 | if(!brainFactory.containsConversationInfo(brainCell.function())) { 66 | return object; 67 | } 68 | if(object instanceof String){ 69 | object += "\n\n상태를 취소하려면 '취소'를 입력해주세요.\n30초 동안 아무 작업이 없을 시 자동 초기화됩니다."; 70 | }else if(object instanceof BrainCellResult){ 71 | ((BrainCellResult) object).comment("\n상태를 취소하려면 '취소'를 입력해주세요.\n30초 동안 아무 작업이 없을 시 자동 초기화됩니다."); 72 | } 73 | return object; 74 | } 75 | 76 | private void conversation(BrainCell brainCell, BrainRequest request) throws JsonProcessingException { 77 | if(!brainFactory.containsConversationInfo(brainCell.function())) { 78 | if(!"".equals(brainCell.parent())){ 79 | conversationService.delete(request.getUser()); 80 | } 81 | return; 82 | } 83 | 84 | Conversation conversation = new Conversation(brainCell.function()); 85 | conversation.put(request.getConversation()); 86 | conversation.put("content", request.getContent()); 87 | conversationService.push(request.getUser(), conversation); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/brain/cell/AbstractBrainCell.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.brain.cell; 2 | 3 | 4 | import com.kingbbode.chatbot.autoconfigure.common.request.BrainRequest; 5 | import com.kingbbode.chatbot.autoconfigure.common.result.BrainResult; 6 | 7 | import java.lang.reflect.InvocationTargetException; 8 | 9 | /** 10 | * Created by YG on 2017-01-26. 11 | */ 12 | public abstract class AbstractBrainCell implements BrainCell { 13 | @Override 14 | public String explain() { 15 | return ""; 16 | } 17 | 18 | public static AbstractBrainCell NOT_FOUND_BRAIN_CELL = new AbstractBrainCell() { 19 | @Override 20 | public BrainResult execute(BrainRequest brainRequest) { 21 | return BrainResult.NONE; 22 | } 23 | 24 | @Override 25 | public String explain() { 26 | return "존재하지 않는 기능입니다."; 27 | } 28 | }; 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/brain/cell/ApiBrainCell.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.brain.cell; 2 | 3 | import com.kingbbode.chatbot.autoconfigure.common.request.BrainRequest; 4 | import com.kingbbode.chatbot.autoconfigure.common.result.BrainResult; 5 | import org.apache.commons.lang3.text.WordUtils; 6 | import org.springframework.beans.factory.BeanFactory; 7 | 8 | import java.lang.reflect.InvocationTargetException; 9 | import java.lang.reflect.Method; 10 | 11 | /** 12 | * Created by YG on 2017-01-26. 13 | */ 14 | public class ApiBrainCell extends AbstractBrainCell{ 15 | private String name; 16 | private Method active; 17 | private Object object; 18 | private BeanFactory beanFactory; 19 | 20 | public ApiBrainCell(Class clazz, Method active, BeanFactory beanFactory) { 21 | this.name = WordUtils.uncapitalize(clazz.getSimpleName()); 22 | this.active = active; 23 | this.beanFactory = beanFactory; 24 | } 25 | 26 | @Override 27 | public BrainResult execute(BrainRequest brainRequest) throws InvocationTargetException, IllegalAccessException { 28 | if (!inject()) { 29 | return BrainResult.Builder.FAILED.room(brainRequest.getRoom()).build(); 30 | } 31 | return (BrainResult) active.invoke(object, brainRequest); 32 | } 33 | 34 | private boolean inject() { 35 | if (object != null) { 36 | return true; 37 | } 38 | if (beanFactory.containsBean(name)) { 39 | object = beanFactory.getBean(name); 40 | } 41 | 42 | return object != null; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/brain/cell/BrainCell.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.brain.cell; 2 | 3 | 4 | import com.kingbbode.chatbot.autoconfigure.common.request.BrainRequest; 5 | import com.kingbbode.chatbot.autoconfigure.common.result.BrainResult; 6 | 7 | import java.lang.reflect.InvocationTargetException; 8 | 9 | /** 10 | * Created by YG on 2017-01-26. 11 | */ 12 | public interface BrainCell { 13 | String explain(); 14 | BrainResult execute(BrainRequest brainRequest) throws InvocationTargetException, IllegalAccessException; 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/brain/cell/CommonBrainCell.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.brain.cell; 2 | 3 | import com.kingbbode.chatbot.autoconfigure.common.enums.BrainResponseType; 4 | import com.kingbbode.chatbot.autoconfigure.common.exception.ArgumentInvalidException; 5 | import com.kingbbode.chatbot.autoconfigure.common.exception.BrainException; 6 | import com.kingbbode.chatbot.autoconfigure.common.exception.InvalidReturnTypeException; 7 | import com.kingbbode.chatbot.autoconfigure.common.request.BrainRequest; 8 | import com.kingbbode.chatbot.autoconfigure.common.result.BrainCellResult; 9 | import com.kingbbode.chatbot.autoconfigure.common.result.BrainResult; 10 | import org.apache.commons.lang3.text.WordUtils; 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | import org.springframework.beans.factory.BeanFactory; 14 | 15 | import java.lang.reflect.InvocationTargetException; 16 | import java.lang.reflect.Method; 17 | 18 | /** 19 | * Created by YG on 2017-01-23. 20 | */ 21 | public class CommonBrainCell extends AbstractBrainCell{ 22 | private final Logger logger = LoggerFactory.getLogger(this.getClass()); 23 | 24 | private String name; 25 | private Method active; 26 | private Object object; 27 | private BeanFactory beanFactory; 28 | private com.kingbbode.chatbot.autoconfigure.common.annotations.BrainCell brain; 29 | 30 | public CommonBrainCell(com.kingbbode.chatbot.autoconfigure.common.annotations.BrainCell brain, Class clazz, Method active, BeanFactory beanFactory) { 31 | this.name = WordUtils.uncapitalize(clazz.getSimpleName()); 32 | this.brain = brain; 33 | this.active = active; 34 | this.beanFactory = beanFactory; 35 | } 36 | 37 | @Override 38 | public String explain() { 39 | return brain.explain(); 40 | } 41 | 42 | @Override 43 | public BrainResult execute(BrainRequest brainRequest) { 44 | if (!inject()) { 45 | return BrainResult.Builder.FAILED.room(brainRequest.getRoom()).build(); 46 | } 47 | Object result; 48 | try { 49 | result = active.invoke(object, brainRequest); 50 | }catch(Throwable e){ 51 | if(e.getCause() instanceof BrainException){ 52 | return BrainResult.builder() 53 | .message(e.getCause().getMessage()) 54 | .room(brainRequest.getRoom()) 55 | .type(BrainResponseType.MESSAGE) 56 | .build(); 57 | }else if(e.getCause() instanceof ArgumentInvalidException){ 58 | return BrainResult.builder() 59 | .message(active.getAnnotation(com.kingbbode.chatbot.autoconfigure.common.annotations.BrainCell.class).example()) 60 | .room(brainRequest.getRoom()) 61 | .type(BrainResponseType.MESSAGE) 62 | .build(); 63 | }else if(e.getCause() instanceof InvalidReturnTypeException){ 64 | return BrainResult.builder() 65 | .message("Method Return Type Exception!") 66 | .room(brainRequest.getRoom()) 67 | .type(BrainResponseType.MESSAGE) 68 | .build(); 69 | } 70 | return BrainResult.builder() 71 | .message("Server Error : " + e.getMessage()) 72 | .room(brainRequest.getRoom()) 73 | .type(BrainResponseType.MESSAGE) 74 | .build(); 75 | } 76 | if(result instanceof BrainCellResult){ 77 | return BrainResult.builder() 78 | .result((BrainCellResult) result) 79 | .type(brain.type()) 80 | .build(); 81 | } 82 | 83 | return BrainResult.builder() 84 | .message((String) result) 85 | .room(brainRequest.getRoom()) 86 | .type(brain.type()) 87 | .build(); 88 | } 89 | 90 | private boolean inject() { 91 | if (object != null) { 92 | return true; 93 | } 94 | if (beanFactory.containsBean(name)) { 95 | object = beanFactory.getBean(name); 96 | } 97 | 98 | return object != null; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/brain/cell/EmoticonBrainCell.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.brain.cell; 2 | 3 | import com.kingbbode.chatbot.autoconfigure.base.emoticon.component.EmoticonComponent; 4 | import com.kingbbode.chatbot.autoconfigure.common.enums.BrainResponseType; 5 | import com.kingbbode.chatbot.autoconfigure.common.request.BrainRequest; 6 | import com.kingbbode.chatbot.autoconfigure.common.result.BrainResult; 7 | 8 | import java.lang.reflect.InvocationTargetException; 9 | 10 | /** 11 | * Created by YG on 2017-01-26. 12 | */ 13 | public class EmoticonBrainCell extends AbstractBrainCell{ 14 | 15 | private EmoticonComponent emoticonComponent; 16 | 17 | public EmoticonBrainCell(EmoticonComponent emoticonComponent) { 18 | this.emoticonComponent = emoticonComponent; 19 | } 20 | 21 | @Override 22 | public BrainResult execute(BrainRequest brainRequest) { 23 | String result = emoticonComponent.get(brainRequest.getContent()); 24 | if(result == null){ 25 | return BrainResult.NONE; 26 | } 27 | return BrainResult.builder() 28 | .message(result) 29 | .room(brainRequest.getRoom()) 30 | .type(BrainResponseType.EMOTICON) 31 | .build(); 32 | 33 | 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/brain/cell/KnowledgeBrainCell.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.brain.cell; 2 | 3 | import com.kingbbode.chatbot.autoconfigure.base.knowledge.component.KnowledgeComponent; 4 | import com.kingbbode.chatbot.autoconfigure.common.request.BrainRequest; 5 | import com.kingbbode.chatbot.autoconfigure.common.result.BrainResult; 6 | 7 | import java.lang.reflect.InvocationTargetException; 8 | import java.util.List; 9 | import java.util.Random; 10 | 11 | /** 12 | * Created by YG on 2017-01-26. 13 | */ 14 | public class KnowledgeBrainCell extends AbstractBrainCell { 15 | private KnowledgeComponent knowledgeComponent; 16 | 17 | public KnowledgeBrainCell(KnowledgeComponent knowledgeComponent) { 18 | this.knowledgeComponent = knowledgeComponent; 19 | } 20 | 21 | @Override 22 | public String explain() { 23 | return "사용자 학습 기능 입니다."; 24 | } 25 | 26 | @Override 27 | public BrainResult execute(BrainRequest brainRequest) { 28 | List results = knowledgeComponent.get(brainRequest.getContent()); 29 | if(results == null){ 30 | return BrainResult.NONE; 31 | } 32 | 33 | return BrainResult.builder() 34 | .message(results.get(new Random().nextInt(results.size()))) 35 | .room(brainRequest.getRoom()) 36 | .build(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/brain/factory/BrainFactory.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.brain.factory; 2 | 3 | import com.kingbbode.chatbot.autoconfigure.ChatbotProperties; 4 | import com.kingbbode.chatbot.autoconfigure.base.emoticon.component.EmoticonComponent; 5 | import com.kingbbode.chatbot.autoconfigure.base.knowledge.component.KnowledgeComponent; 6 | import com.kingbbode.chatbot.autoconfigure.brain.cell.*; 7 | import com.kingbbode.chatbot.autoconfigure.common.annotations.Brain; 8 | import com.kingbbode.chatbot.autoconfigure.common.annotations.BrainCell; 9 | import com.kingbbode.chatbot.autoconfigure.common.enums.BrainRequestType; 10 | import com.kingbbode.chatbot.autoconfigure.common.properties.BotProperties; 11 | import org.apache.commons.lang3.text.WordUtils; 12 | import org.reflections.Reflections; 13 | import org.reflections.scanners.SubTypesScanner; 14 | import org.reflections.scanners.TypeAnnotationsScanner; 15 | import org.reflections.util.ClasspathHelper; 16 | import org.reflections.util.ConfigurationBuilder; 17 | import org.slf4j.Logger; 18 | import org.slf4j.LoggerFactory; 19 | import org.springframework.beans.factory.BeanFactory; 20 | import org.springframework.beans.factory.annotation.Autowired; 21 | 22 | import javax.annotation.PostConstruct; 23 | import java.io.IOException; 24 | import java.lang.reflect.InvocationTargetException; 25 | import java.lang.reflect.Method; 26 | import java.util.HashMap; 27 | import java.util.HashSet; 28 | import java.util.Map; 29 | import java.util.Set; 30 | import java.util.stream.Collectors; 31 | 32 | import static com.kingbbode.chatbot.autoconfigure.brain.cell.AbstractBrainCell.NOT_FOUND_BRAIN_CELL; 33 | 34 | /** 35 | * Created by YG on 2017-01-23. 36 | */ 37 | public class BrainFactory { 38 | 39 | private static final Logger logger = LoggerFactory.getLogger(BrainFactory.class); 40 | 41 | @Autowired 42 | private BotProperties botProperties; 43 | 44 | @Autowired 45 | private BeanFactory beanFactory; 46 | 47 | @Autowired 48 | private EmoticonComponent emoticon; 49 | 50 | @Autowired 51 | private KnowledgeComponent knowledge; 52 | 53 | @Autowired 54 | private ChatbotProperties chatbotProperties; 55 | 56 | private KnowledgeBrainCell knowledgeBrainCell; 57 | 58 | private EmoticonBrainCell emoticonBrainCell; 59 | 60 | //#command, functionKey 61 | private Map commandMap; 62 | //functionKey, BrainCell 63 | private Map keyMap; 64 | //functionKey, ConversationInfo 65 | private Map conversationInfoMap; 66 | 67 | //private Map brainCellMap; 68 | 69 | @PostConstruct 70 | public void init() throws InvocationTargetException, IllegalAccessException, IOException { 71 | knowledgeBrainCell = new KnowledgeBrainCell(knowledge); 72 | emoticonBrainCell = new EmoticonBrainCell(emoticon); 73 | this.load(false); 74 | } 75 | 76 | public void update() throws IOException, InvocationTargetException, IllegalAccessException { 77 | this.load(true); 78 | } 79 | 80 | @SuppressWarnings("unchecked") 81 | public void load(boolean isUpdate) throws InvocationTargetException, IllegalAccessException, IOException { 82 | if(isUpdate){ 83 | knowledge.init(); 84 | emoticon.init(); 85 | } 86 | Set keyChecker = new HashSet<>(); 87 | Map command = new HashMap<>(); 88 | Map> childCommand = new HashMap<>(); 89 | Map key = new HashMap<>(); 90 | Map conversationInfo = new HashMap<>(); 91 | registerDefault(keyChecker, command, childCommand, key); 92 | Reflections reflections = new Reflections(new ConfigurationBuilder() 93 | .setUrls(ClasspathHelper.forPackage(chatbotProperties.getBasePackage())).setScanners( 94 | new TypeAnnotationsScanner(), new SubTypesScanner())); 95 | for(Class clazz : reflections.getTypesAnnotatedWith(Brain.class)){ 96 | if(clazz.getAnnotation(Brain.class).request() == BrainRequestType.COMMON) { 97 | registerCommonBrainCellByClass(keyChecker, command, childCommand, key, clazz); 98 | }else if(clazz.getAnnotation(Brain.class).request() == BrainRequestType.API){ 99 | registerApiBrainCellByClass(isUpdate, command, key, clazz); 100 | } 101 | } 102 | 103 | childCommand.forEach((key2, value2) -> { 104 | ConversationInfo info = new ConversationInfo(); 105 | value2.forEach((key1, value1) -> { 106 | if (key1.equals(key2 + "query")) { 107 | info.setQuery(value1); 108 | } else { 109 | info.add(key1, value1); 110 | } 111 | }); 112 | conversationInfo.put(key2, info); 113 | }); 114 | logger.info("Load Brain command : {}, key : {}, conversation : {}", command.size(), key.size(), conversationInfo.size()); 115 | this.commandMap = command; 116 | this.keyMap = key; 117 | this.conversationInfoMap = conversationInfo; 118 | } 119 | 120 | private void registerDefault(Set keyChecker, Map command, Map> childCommand, Map key) { 121 | Reflections defaults = new Reflections(new ConfigurationBuilder() 122 | .setUrls(ClasspathHelper.forPackage("com.kingbbode.chatbot.autoconfigure.base")).setScanners( 123 | new TypeAnnotationsScanner(), new SubTypesScanner())); 124 | for(Class clazz : defaults.getTypesAnnotatedWith(Brain.class)){ 125 | if(clazz.getAnnotation(Brain.class).request() == BrainRequestType.COMMON) { 126 | if("EmoticonBrain".equals(clazz.getSimpleName()) && !chatbotProperties.isEnableEmoticon()){ 127 | continue; 128 | }else if("KnowledgeBrain".equals(clazz.getSimpleName()) && !chatbotProperties.isEnableKnowledge()){ 129 | continue; 130 | }else if("BaseBrain".equals(clazz.getSimpleName()) && !chatbotProperties.isEnableBase()){ 131 | continue; 132 | } 133 | registerCommonBrainCellByClass(keyChecker, command, childCommand, key, clazz); 134 | } 135 | } 136 | } 137 | 138 | @SuppressWarnings("unchecked") 139 | private void registerApiBrainCellByClass(boolean isUpdate, Map command, Map key, Class clazz) throws IllegalAccessException, InvocationTargetException { 140 | Method execute = null; 141 | Method getCommands = null; 142 | Method update = null; 143 | for(Method method : clazz.getMethods()){ 144 | switch (method.getName()) { 145 | case "execute": 146 | execute = method; 147 | break; 148 | case "getCommands": 149 | getCommands = method; 150 | break; 151 | case "update": 152 | update = method; 153 | break; 154 | } 155 | } 156 | if(execute == null || getCommands == null){ 157 | return; 158 | } 159 | if(isUpdate && update != null){ 160 | update.invoke(beanFactory.getBean(WordUtils.uncapitalize(clazz.getSimpleName()))); 161 | } 162 | Set list = (Set) getCommands.invoke(beanFactory.getBean(WordUtils.uncapitalize(clazz.getSimpleName()))); 163 | for(String cmd : list){ 164 | command.put(cmd, cmd); 165 | key.put(cmd, new ApiBrainCell(clazz, execute, beanFactory)); 166 | } 167 | } 168 | 169 | private void registerCommonBrainCellByClass(Set keyChecker, Map command, Map> childCommand, Map key, Class clazz) { 170 | for (Method method : clazz.getMethods()) { 171 | if (method.isAnnotationPresent(BrainCell.class)) { 172 | BrainCell brainCell = method.getAnnotation(BrainCell.class); 173 | if("".equals(brainCell.parent())) { 174 | command.put(botProperties.getCommandPrefix() + brainCell.key(), brainCell.function()); 175 | }else{ 176 | if(!childCommand.containsKey(brainCell.parent())){ 177 | childCommand.put(brainCell.parent(), new HashMap<>()); 178 | } 179 | childCommand.get(brainCell.parent()).put(brainCell.key().equals("query")?brainCell.parent() + brainCell.key():brainCell.key(), brainCell.function()); 180 | } 181 | key.put(brainCell.function(), new CommonBrainCell(brainCell, clazz, method, beanFactory)); 182 | String chkKey = brainCell.parent() + brainCell.key(); 183 | if(keyChecker.contains(chkKey)){ 184 | throw new RuntimeException("중복된 Key 값이 존재합니다." + chkKey); 185 | } 186 | keyChecker.add(chkKey); 187 | } 188 | } 189 | } 190 | 191 | @SuppressWarnings("unchecked") 192 | public T get(String command){ 193 | if(commandMap.containsKey(command)){ 194 | return (T) keyMap.get(commandMap.get(command)); 195 | } 196 | return (T)( 197 | ( 198 | chatbotProperties.isEnableEmoticon() && 199 | command.startsWith(botProperties.getEmoticonPrefix()) && 200 | emoticon.contains(command.substring(1, command.length())) 201 | )? 202 | emoticonBrainCell : 203 | (chatbotProperties.isEnableKnowledge()? 204 | knowledgeBrainCell: 205 | NOT_FOUND_BRAIN_CELL)); 206 | } 207 | 208 | public boolean containsFunctionKey(String function){ 209 | return keyMap.containsKey(function); 210 | } 211 | 212 | @SuppressWarnings("unchecked") 213 | public T getByFunctionKey(String function){ 214 | return (T) keyMap.get(function); 215 | } 216 | 217 | public boolean containsConversationInfo(String function){ 218 | return conversationInfoMap.containsKey(function); 219 | } 220 | 221 | public ConversationInfo getConversationInfo(String function){ 222 | return conversationInfoMap.get(function); 223 | } 224 | 225 | @SuppressWarnings("unchecked") 226 | public Set> findBrainCellByType(Class type){ 227 | return commandMap.entrySet().stream() 228 | .filter(entry -> keyMap.containsKey(entry.getValue())) 229 | .filter(entry -> keyMap.get(entry.getValue()).getClass().equals(type)) 230 | .map(entry -> new BrainCellInfo<>(entry.getKey(), (T) keyMap.get(entry.getValue()))) 231 | .collect(Collectors.toSet()); 232 | } 233 | 234 | public static class BrainCellInfo { 235 | private String command; 236 | private T brainCell; 237 | 238 | BrainCellInfo(String command, T brainCell) { 239 | this.command = command; 240 | this.brainCell = brainCell; 241 | } 242 | 243 | @Override 244 | public String toString() { 245 | return command + 246 | " : " + 247 | brainCell.explain(); 248 | } 249 | 250 | public String getCommand() { 251 | return command; 252 | } 253 | } 254 | 255 | public static class ConversationInfo { 256 | private Map afters = new HashMap<>(); 257 | private String query; 258 | 259 | public void setQuery(String query) { 260 | this.query = query; 261 | } 262 | 263 | void add(String key, String value){ 264 | afters.put(key, value); 265 | } 266 | 267 | 268 | public String findFunctionKey(String command){ 269 | if(afters.containsKey(command)){ 270 | return afters.get(command); 271 | } 272 | return query; 273 | } 274 | 275 | public String example() { 276 | StringBuilder builder = new StringBuilder(); 277 | this.afters.keySet().forEach(key -> { 278 | builder.append("'"); 279 | builder.append(key); 280 | builder.append("'"); 281 | builder.append(" "); 282 | }); 283 | 284 | return builder.toString() + "중에 입력해주세요."; 285 | } 286 | } 287 | } 288 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/common/annotations/Brain.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.common.annotations; 2 | 3 | import com.kingbbode.chatbot.autoconfigure.common.enums.BrainRequestType; 4 | import org.springframework.stereotype.Component; 5 | 6 | import java.lang.annotation.ElementType; 7 | import java.lang.annotation.Retention; 8 | import java.lang.annotation.RetentionPolicy; 9 | import java.lang.annotation.Target; 10 | 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Target(ElementType.TYPE) 13 | @Component 14 | public @interface Brain { 15 | BrainRequestType request() default BrainRequestType.COMMON; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/common/annotations/BrainCell.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.common.annotations; 2 | 3 | 4 | import com.kingbbode.chatbot.autoconfigure.common.enums.BrainResponseType; 5 | 6 | import java.lang.annotation.ElementType; 7 | import java.lang.annotation.Retention; 8 | import java.lang.annotation.RetentionPolicy; 9 | import java.lang.annotation.Target; 10 | 11 | /** 12 | * Bot 두뇌의 지식을 지정하는 Annotation 13 | * @author YG 14 | * @key 명령어 Key 15 | */ 16 | @Retention(RetentionPolicy.RUNTIME) 17 | @Target(ElementType.METHOD) 18 | public @interface BrainCell { 19 | String parent() default ""; 20 | String key() default "query"; 21 | String explain() default ""; 22 | String example() default ""; 23 | String function(); 24 | boolean cancelable() default true; 25 | BrainResponseType type() default BrainResponseType.MESSAGE; 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/common/enums/BrainRequestType.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.common.enums; 2 | 3 | /** 4 | * Created by YG on 2017-01-26. 5 | */ 6 | public enum BrainRequestType { 7 | COMMON, 8 | API 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/common/enums/BrainResponseType.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.common.enums; 2 | 3 | /** 4 | * Created by YG on 2016-10-14. 5 | */ 6 | public enum BrainResponseType { 7 | MESSAGE, 8 | FEED, 9 | EMOTICON, 10 | OUT, 11 | NONE 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/common/enums/GrantType.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.common.enums; 2 | 3 | /** 4 | * Created by YG on 2016-10-14. 5 | */ 6 | public enum GrantType { 7 | PASSWORD("password"), 8 | REFRESH("refresh_token"); 9 | 10 | String key; 11 | 12 | GrantType(String key) { 13 | this.key = key; 14 | } 15 | 16 | public String getKey() { 17 | return key; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/common/exception/ArgumentInvalidException.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.common.exception; 2 | 3 | import java.lang.reflect.UndeclaredThrowableException; 4 | 5 | /** 6 | * Created by YG on 2017-02-08. 7 | */ 8 | public class ArgumentInvalidException extends UndeclaredThrowableException { 9 | 10 | 11 | 12 | public ArgumentInvalidException(Throwable undeclaredThrowable) { 13 | super(undeclaredThrowable); 14 | } 15 | 16 | public ArgumentInvalidException(Throwable undeclaredThrowable, String s) { 17 | super(undeclaredThrowable, s); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/common/exception/BrainException.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.common.exception; 2 | 3 | import java.lang.reflect.UndeclaredThrowableException; 4 | 5 | /** 6 | * Created by YG on 2017-02-08. 7 | */ 8 | public class BrainException extends UndeclaredThrowableException { 9 | 10 | 11 | 12 | public BrainException(Throwable undeclaredThrowable) { 13 | super(undeclaredThrowable); 14 | } 15 | 16 | public BrainException(Throwable undeclaredThrowable, String s) { 17 | super(undeclaredThrowable, s); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/common/exception/InvalidReturnTypeException.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.common.exception; 2 | 3 | import java.lang.reflect.UndeclaredThrowableException; 4 | 5 | /** 6 | * Created by YG on 2017-02-08. 7 | */ 8 | public class InvalidReturnTypeException extends UndeclaredThrowableException { 9 | 10 | public InvalidReturnTypeException(Throwable undeclaredThrowable) { 11 | super(undeclaredThrowable); 12 | } 13 | 14 | public InvalidReturnTypeException(Throwable undeclaredThrowable, String s) { 15 | super(undeclaredThrowable, s); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/common/interfaces/Dispatcher.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.common.interfaces; 2 | 3 | /** 4 | * Created by YG on 2017-07-10. 5 | */ 6 | public interface Dispatcher { 7 | void dispatch(T event); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/common/interfaces/MemberService.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.common.interfaces; 2 | 3 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.response.RoomInfoResponse; 4 | 5 | /** 6 | * Created by YG on 2017-07-10. 7 | */ 8 | public interface MemberService { 9 | void update(); 10 | 11 | String get(String memberId); 12 | 13 | boolean contains(String memberId); 14 | 15 | RoomInfoResponse getRoomInfo(String room); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/common/properties/BotProperties.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.common.properties; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | /** 7 | * Created by YG on 2016-10-13. 8 | */ 9 | @Getter 10 | @Setter 11 | public class BotProperties { 12 | private String name; 13 | private String commandPrefix; 14 | private String emoticonPrefix; 15 | private boolean testMode; 16 | 17 | public BotProperties(String name, String commandPrefix, String emoticonPrefix, boolean testMode) { 18 | this.name = name; 19 | this.commandPrefix = commandPrefix; 20 | this.emoticonPrefix = emoticonPrefix; 21 | this.testMode = testMode; 22 | } 23 | 24 | public boolean isTestMode() { 25 | return testMode; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/common/request/BrainRequest.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.common.request; 2 | 3 | 4 | import com.kingbbode.chatbot.autoconfigure.conversation.Conversation; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import org.springframework.util.StringUtils; 8 | 9 | /** 10 | * Created by YG on 2017-01-23. 11 | */ 12 | @Data 13 | @Builder 14 | public class BrainRequest { 15 | private String messageNo; 16 | private String team; 17 | private String user; 18 | private String room; 19 | 20 | 21 | private String content; 22 | private Conversation conversation; 23 | /* 24 | public BrainRequest(EventResponse.Event.Chat chat, MessageResponse.Message message) { 25 | this.user = String.valueOf(message.getUser()); 26 | this.room = chat.getRoom(); 27 | this.content = message.getContent()!=null?message.getContent().trim():null; 28 | this.messageNo = String.valueOf(message.getMsg()); 29 | this.team = String.valueOf(chat.getTeam()); 30 | } 31 | 32 | public BrainRequest(String user, String room, String content) { 33 | this.user = user; 34 | this.room = room; 35 | this.content = content; 36 | }*/ 37 | 38 | public boolean isValid(){ 39 | return !StringUtils.isEmpty(content); 40 | } 41 | 42 | @Override 43 | public String toString() { 44 | return "BrainRequest{\n" + 45 | "team=" + team + "\n" + 46 | "message no=" + messageNo + "\n" + 47 | "user='" + user + "\n" + 48 | "room='" + room + "\n" + 49 | "\n}"; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/common/result/BrainCellResult.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.common.result; 2 | 3 | /** 4 | * Created by YG on 2017-01-26. 5 | */ 6 | public class BrainCellResult { 7 | private String message; 8 | private String room; 9 | private Boolean example; 10 | 11 | public BrainCellResult(Builder builder) { 12 | this.message = builder.message; 13 | this.room = builder.room; 14 | this.example = builder.example; 15 | } 16 | 17 | public String getMessage() { 18 | return message; 19 | } 20 | 21 | public String getRoom() { 22 | return room; 23 | } 24 | 25 | public void comment(String comment){ 26 | this.message += comment; 27 | } 28 | 29 | public static class Builder { 30 | private String message; 31 | private String room; 32 | private Boolean example = false; 33 | 34 | public Builder message(String message){ 35 | this.message = message; 36 | return this; 37 | } 38 | 39 | public Builder room(String room){ 40 | this.room = room; 41 | return this; 42 | } 43 | 44 | public Builder example(boolean example){ 45 | this.example = example; 46 | return this; 47 | } 48 | 49 | public BrainCellResult build() { 50 | return new BrainCellResult(this); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/common/result/BrainResult.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.common.result; 2 | 3 | import com.kingbbode.chatbot.autoconfigure.common.enums.BrainResponseType; 4 | import org.apache.commons.lang3.StringUtils; 5 | 6 | /** 7 | * Created by YG on 2017-01-26. 8 | */ 9 | public class BrainResult { 10 | public static BrainResult NONE = builder().type(BrainResponseType.NONE).build(); 11 | 12 | private BrainResponseType type; 13 | private String message; 14 | private String room; 15 | 16 | public BrainResult(Builder builder) { 17 | this.type = builder.type; 18 | this.message = builder.message; 19 | this.room = builder.room; 20 | } 21 | 22 | public BrainResponseType type() { 23 | return type; 24 | } 25 | 26 | public String getMessage() { 27 | return message; 28 | } 29 | 30 | public String getRoom() { 31 | return room; 32 | } 33 | 34 | public static Builder builder() { 35 | return new Builder(); 36 | } 37 | 38 | public static class Builder { 39 | private BrainResponseType type; 40 | private String message; 41 | private String room; 42 | 43 | public Builder(){ 44 | this.type = BrainResponseType.MESSAGE; 45 | } 46 | 47 | public Builder result(BrainCellResult result){ 48 | this.message(result.getMessage()); 49 | if(!StringUtils.isEmpty(result.getRoom())) { 50 | this.room(result.getRoom()); 51 | } 52 | return this; 53 | } 54 | 55 | public Builder type(BrainResponseType type) { 56 | this.type = type; 57 | return this; 58 | } 59 | 60 | public Builder message(String message){ 61 | this.message = message; 62 | return this; 63 | } 64 | 65 | public Builder room(String room){ 66 | this.room = room; 67 | return this; 68 | } 69 | 70 | public BrainResult build() { 71 | if(this.message == null || this.room == null){ 72 | return NONE; 73 | } 74 | return new BrainResult(this); 75 | } 76 | public static Builder FAILED = new Builder() 77 | .message("해당 기능은 장애 상태 입니다"); 78 | public static Builder GREETING = new Builder() 79 | .message("안녕하세요.\n '기능'을 참고하세요"); 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/common/result/CommonResult.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.common.result; 2 | 3 | /** 4 | * Created by YG on 2016-06-22. 5 | */ 6 | public class CommonResult { 7 | 8 | CommonResult(boolean success, String message){ 9 | this.success = success; 10 | this.message = message; 11 | } 12 | 13 | private boolean success; 14 | 15 | private String message; 16 | 17 | public boolean isSuccess() { 18 | return success; 19 | } 20 | 21 | public void setSuccess(boolean success) { 22 | this.success = success; 23 | } 24 | 25 | public String getMessage() { 26 | return message; 27 | } 28 | 29 | public void setMessage(String message) { 30 | this.message = message; 31 | } 32 | 33 | public static CommonResult createSuccess(String message){ 34 | return new CommonResult(true, message); 35 | } 36 | 37 | public static CommonResult createFail(String message){ 38 | return new CommonResult(false, message); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/common/util/BrainUtil.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.common.util; 2 | 3 | import com.kingbbode.chatbot.autoconfigure.brain.cell.AbstractBrainCell; 4 | import com.kingbbode.chatbot.autoconfigure.brain.factory.BrainFactory; 5 | 6 | import java.util.List; 7 | import java.util.Map; 8 | import java.util.Set; 9 | 10 | /** 11 | * Created by YG on 2016-04-12. 12 | */ 13 | public class BrainUtil { 14 | 15 | public static String explainDetail(Set> entrySet) { 16 | StringBuilder stringBuilder = new StringBuilder(); 17 | entrySet 18 | .forEach(info -> { 19 | stringBuilder.append(info.toString()); 20 | stringBuilder.append("\n"); 21 | } 22 | ); 23 | return stringBuilder.toString(); 24 | } 25 | 26 | public static String explainForKnowledge(Set>> entrySet) { 27 | StringBuilder stringBuilder = new StringBuilder(); 28 | entrySet 29 | .forEach(entry -> { 30 | stringBuilder.append(entry.getKey()); 31 | stringBuilder.append(" - 지식깊이 : "); 32 | stringBuilder.append(entry.getValue().size()); 33 | stringBuilder.append("\n"); 34 | }); 35 | 36 | return stringBuilder.toString(); 37 | } 38 | 39 | public static String explainForEmoticon(Map map) { 40 | StringBuilder stringBuilder = new StringBuilder(); 41 | map.forEach((key, value) -> { 42 | stringBuilder.append(key); 43 | stringBuilder.append("\n"); 44 | }); 45 | return stringBuilder.toString(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/common/util/RestTemplateFactory.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.common.util; 2 | 3 | import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; 4 | import org.springframework.http.converter.ByteArrayHttpMessageConverter; 5 | import org.springframework.http.converter.FormHttpMessageConverter; 6 | import org.springframework.http.converter.HttpMessageConverter; 7 | import org.springframework.http.converter.StringHttpMessageConverter; 8 | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; 9 | import org.springframework.web.client.RestOperations; 10 | import org.springframework.web.client.RestTemplate; 11 | 12 | import java.nio.charset.Charset; 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | 16 | /** 17 | * Created by YG on 2017-01-20. 18 | */ 19 | public class RestTemplateFactory { 20 | public static RestOperations getRestOperations(HttpComponentsClientHttpRequestFactory factory) { 21 | RestTemplate restTemplate = new RestTemplate(factory); 22 | 23 | StringHttpMessageConverter stringMessageConverter = new StringHttpMessageConverter(Charset.forName("UTF-8")); 24 | MappingJackson2HttpMessageConverter jackson2Converter = new MappingJackson2HttpMessageConverter(); 25 | ByteArrayHttpMessageConverter byteArrayHttpMessageConverter = new ByteArrayHttpMessageConverter(); 26 | FormHttpMessageConverter formHttpMessageConverter = new FormHttpMessageConverter(); 27 | formHttpMessageConverter.setCharset(Charset.forName("UTF-8")); 28 | 29 | List> converters = new ArrayList<>(); 30 | converters.add(jackson2Converter); 31 | converters.add(stringMessageConverter); 32 | converters.add(byteArrayHttpMessageConverter); 33 | converters.add(formHttpMessageConverter); 34 | 35 | restTemplate.setMessageConverters(converters); 36 | return restTemplate; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/conversation/Conversation.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.conversation; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * Created by YG on 2017-04-03. 8 | */ 9 | public class Conversation { 10 | private String function; 11 | private Map param; 12 | 13 | public Conversation() { 14 | } 15 | 16 | public Conversation(String function) { 17 | this.function = function; 18 | this.param = new HashMap<>(); 19 | } 20 | 21 | public String getFunction() { 22 | return function; 23 | } 24 | 25 | public Map getParam() { 26 | return param; 27 | } 28 | 29 | public void put(String key, String value) { 30 | param.put(key, value); 31 | } 32 | 33 | public void setParam(Map param) { 34 | this.param = param; 35 | } 36 | 37 | public void setFunction(String function) { 38 | this.function = function; 39 | } 40 | 41 | public void put(Conversation conversation) { 42 | if(conversation != null) { 43 | this.param.putAll(conversation.param); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/conversation/ConversationService.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.conversation; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | import com.kingbbode.chatbot.autoconfigure.common.properties.BotProperties; 6 | import org.joda.time.DateTime; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.core.env.Environment; 9 | import org.springframework.data.redis.core.ListOperations; 10 | import org.springframework.data.redis.core.RedisTemplate; 11 | 12 | import javax.annotation.PostConstruct; 13 | import javax.annotation.Resource; 14 | import java.io.IOException; 15 | 16 | /** 17 | * Created by YG on 2017-04-03. 18 | */ 19 | public class ConversationService { 20 | 21 | @Autowired 22 | private Environment environment; 23 | 24 | @Resource(name = "redisTemplate") 25 | private RedisTemplate redisTemplate; 26 | 27 | @Resource(name = "redisTemplate") 28 | private ListOperations listOperations; 29 | 30 | @Autowired 31 | private ObjectMapper objectMapper; 32 | 33 | @Autowired 34 | private BotProperties botProperties; 35 | 36 | private static final String REDIS_KEY = ":conversation:"; 37 | 38 | private String key; 39 | private int expireTime; 40 | 41 | @PostConstruct 42 | private void init() { 43 | this.key = botProperties.isTestMode() ? "test:" + botProperties.getName() + REDIS_KEY : botProperties.getName() + REDIS_KEY; 44 | this.expireTime = environment.acceptsProfiles("dev") ? 300 : 30; 45 | } 46 | 47 | 48 | public Conversation pop(String userId) throws IOException { 49 | String result = listOperations.rightPop(this.key + userId); 50 | if (result != null) { 51 | redisTemplate.expireAt(this.key + userId, new DateTime().plusSeconds(expireTime).toDate()); 52 | } 53 | return result != null ? objectMapper.readValue(listOperations.rightPop(this.key + userId), Conversation.class) : null; 54 | } 55 | 56 | public void push(String userId, Conversation value) throws JsonProcessingException { 57 | listOperations.rightPush(this.key + userId, objectMapper.writeValueAsString(value)); 58 | this.touch(userId); 59 | } 60 | 61 | public void touch(String userId) { 62 | redisTemplate.expireAt(this.key + userId, new DateTime().plusSeconds(expireTime).toDate()); 63 | } 64 | 65 | public Conversation getLatest(String userId) throws IOException { 66 | String result = listOperations.index(this.key + userId, listOperations.size(this.key + userId) - 1); 67 | if (result != null) { 68 | redisTemplate.expireAt(this.key + userId, new DateTime().plusSeconds(expireTime).toDate()); 69 | } 70 | return result != null ? objectMapper.readValue(result, Conversation.class) : null; 71 | } 72 | 73 | public void delete(String userId) { 74 | redisTemplate.opsForValue().getOperations().delete(this.key + userId); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/event/Event.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.event; 2 | 3 | import com.kingbbode.chatbot.autoconfigure.common.interfaces.Dispatcher; 4 | import lombok.Data; 5 | 6 | /** 7 | * Created by YG on 2017-07-10. 8 | */ 9 | @Data 10 | public class Event { 11 | private Dispatcher dispatcher; 12 | private T item; 13 | 14 | public Event(Dispatcher dispatcher, T item) { 15 | this.dispatcher = dispatcher; 16 | this.item = item; 17 | } 18 | 19 | public void execute(){ 20 | dispatcher.dispatch(item); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/event/EventQueue.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.event; 2 | 3 | import java.util.Queue; 4 | import java.util.concurrent.ConcurrentLinkedQueue; 5 | 6 | /** 7 | * Created by YG on 2016-11-03. 8 | */ 9 | public class EventQueue { 10 | private Queue queue = new ConcurrentLinkedQueue<>(); 11 | 12 | public boolean hasNext(){ 13 | return queue.size()>0; 14 | } 15 | 16 | public void offer(Event e) { 17 | if (e == null) { 18 | return; 19 | } 20 | queue.offer(e); 21 | } 22 | 23 | Event poll() { 24 | return queue.poll(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/event/TaskRunner.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.event; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 5 | import org.springframework.scheduling.annotation.EnableScheduling; 6 | import org.springframework.scheduling.annotation.Scheduled; 7 | import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; 8 | import org.springframework.stereotype.Service; 9 | 10 | import javax.annotation.Resource; 11 | 12 | /** 13 | * Created by YG on 2016-08-17. 14 | */ 15 | @Service 16 | @EnableScheduling 17 | @ConditionalOnProperty(prefix = "chatbot", name = "enabled", havingValue = "true") 18 | public class TaskRunner { 19 | 20 | @Resource(name = "eventQueueTreadPool") 21 | private ThreadPoolTaskExecutor executer; 22 | 23 | @Autowired 24 | private EventQueue eventQueue; 25 | 26 | @Scheduled(fixedDelay = 10) 27 | private void execute(){ 28 | while(eventQueue.hasNext()){ 29 | executer.execute(new FetcherTask(eventQueue.poll())); 30 | } 31 | } 32 | 33 | public static class FetcherTask implements Runnable { 34 | Event event; 35 | FetcherTask(Event event) { 36 | this.event = event; 37 | } 38 | 39 | @Override 40 | public void run() { 41 | this.event.execute(); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/messenger/teamup/Api.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.messenger.teamup; 2 | 3 | /** 4 | * Created by YG on 2017-07-10. 5 | */ 6 | public enum Api { 7 | FEED_WRITE("https://edge.tmup.com/v3/feed/"), 8 | FEED_LIST("https://edge.tmup.com/v3/feedgroups"), 9 | MESSAGE_READ("https://edge.tmup.com/v3/messages/"), 10 | MESSAGE_SEND("https://edge.tmup.com/v3/message/"), 11 | ROOM("https://edge.tmup.com/v3/room/"), 12 | RTM("https://ev.tmup.com/v3/events"), 13 | TOKEN("https://auth.tmup.com/oauth2/token"), 14 | FILE_DOWNLOAD("https://file.tmup.com/v3/file/"), 15 | FILE_UPLOAD("https://file.tmup.com/v3/files/"), 16 | AUTH_ORGANIGRAMME("https://auth.tmup.com/v1/team/"); 17 | 18 | private String url; 19 | 20 | Api(String url) { 21 | this.url = url; 22 | } 23 | 24 | public String getUrl() { 25 | return url; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/messenger/teamup/TeamUpDispatcher.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.messenger.teamup; 2 | 3 | import com.kingbbode.chatbot.autoconfigure.TeamUpProperties; 4 | import com.kingbbode.chatbot.autoconfigure.base.emoticon.component.EmoticonComponent; 5 | import com.kingbbode.chatbot.autoconfigure.brain.DispatcherBrain; 6 | import com.kingbbode.chatbot.autoconfigure.common.enums.BrainResponseType; 7 | import com.kingbbode.chatbot.autoconfigure.common.interfaces.Dispatcher; 8 | import com.kingbbode.chatbot.autoconfigure.common.request.BrainRequest; 9 | import com.kingbbode.chatbot.autoconfigure.common.result.BrainResult; 10 | import com.kingbbode.chatbot.autoconfigure.conversation.Conversation; 11 | import com.kingbbode.chatbot.autoconfigure.conversation.ConversationService; 12 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.message.MessageService; 13 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.request.FileRequest; 14 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.response.EventResponse; 15 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.response.FileUploadResponse; 16 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.response.MessageResponse; 17 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.util.ImagesUtils; 18 | import org.slf4j.Logger; 19 | import org.slf4j.LoggerFactory; 20 | import org.springframework.beans.factory.annotation.Autowired; 21 | 22 | import java.io.IOException; 23 | 24 | /** 25 | * Created by YG on 2017-07-10. 26 | */ 27 | public class TeamUpDispatcher implements Dispatcher { 28 | private final Logger logger = LoggerFactory.getLogger(this.getClass()); 29 | 30 | private static final String EVENT_MESSAGE = "chat.message"; 31 | private static final String EVENT_JOIN = "chat.join"; 32 | private static final int MESSAGE_TYPE = 1; 33 | private static final int FILE_TYPE = 2; 34 | 35 | @Autowired 36 | private MessageService messageService; 37 | 38 | @Autowired 39 | private ConversationService conversationService; 40 | 41 | @Autowired 42 | private EmoticonComponent emoticonComponent; 43 | 44 | @Autowired 45 | private DispatcherBrain dispatcherBrain; 46 | 47 | @Autowired 48 | private TeamUpProperties teamUpProperties; 49 | 50 | @Override 51 | public void dispatch(EventResponse.Event event) { 52 | if (EVENT_MESSAGE.equals(event.getType())) { 53 | if (!teamUpProperties.getBot().contains(event.getChat().getUser())) { 54 | classification(event); 55 | } 56 | } else if (EVENT_JOIN.equals(event.getType())) { 57 | send(BrainResult.Builder.GREETING.room( event.getChat().getRoom()).build()); 58 | } 59 | } 60 | 61 | private void classification(EventResponse.Event event) { 62 | EventResponse.Event.Chat chat = event.getChat(); 63 | MessageResponse.Message message = messageService.readMessage(event.getChat()); 64 | BrainRequest brainRequest = BrainRequest.builder() 65 | .user(String.valueOf(message.getUser())) 66 | .room(chat.getRoom()) 67 | .content(message.getContent()!=null?message.getContent().trim():null) 68 | .messageNo(String.valueOf(message.getMsg())) 69 | .team(chat.getTeam()) 70 | .build(); 71 | switch (message.getType()) { 72 | case MESSAGE_TYPE: 73 | if (!brainRequest.isValid()) { 74 | break; 75 | } 76 | send(dispatcherBrain.execute(brainRequest)); 77 | break; 78 | case FILE_TYPE: 79 | MessageResponse.File file = message.getFile(); 80 | if (!ImagesUtils.isImage(file)) { 81 | break; 82 | } 83 | try { 84 | Conversation conversation = conversationService.getLatest(String.valueOf(message.getUser())); 85 | if(isEmoticonAction(conversation)){ 86 | String[] fileName = file.getName().toLowerCase().split("\\."); 87 | FileUploadResponse response =messageService.writeImage(new FileRequest.Builder() 88 | .request(brainRequest) 89 | .id(file.getId()) 90 | .name(message.getUser() + fileName[0]) 91 | .type(ImagesUtils.selectMediaTypeForImage(fileName[1])) 92 | .build() 93 | ); 94 | if(response == null || response.getFiles() == null || response.getFiles().size()<1){ 95 | conversationService.delete(String.valueOf(message.getUser())); 96 | send(BrainResult.builder() 97 | .message("문제가 있네요.. 다음에 이용해주세요..ㅜㅜ") 98 | .room(event.getChat().getRoom()) 99 | .type(BrainResponseType.MESSAGE) 100 | .build()); 101 | break; 102 | } 103 | emoticonComponent.put(conversation.getParam().get("name"), response.getFiles().get(0).getId()); 104 | logger.info("emoticon reg - user : {}, emoticon: {}", message.getUser(), conversation.getParam().get("name")); 105 | conversationService.delete(String.valueOf(message.getUser())); 106 | send(BrainResult.builder() 107 | .message(conversation.getParam().get("name") + " 이모티콘이 등록되었습니다.") 108 | .room(event.getChat().getRoom()) 109 | .type(BrainResponseType.MESSAGE) 110 | .build()); 111 | break; 112 | } 113 | break; 114 | } catch (IOException e) { 115 | logger.error("emoticon reg exception - user : {}", message.getUser()); 116 | break; 117 | } 118 | } 119 | } 120 | 121 | private boolean isEmoticonAction(Conversation conversation) { 122 | return conversation != null && conversation.getFunction().equals("emoticonReg1") && conversation.getParam().containsKey("name"); 123 | } 124 | 125 | private void send(BrainResult result) { 126 | if(result!=null) { 127 | switch (result.type()) { 128 | case MESSAGE: 129 | messageService.sendMessage(result); 130 | break; 131 | case FEED: 132 | messageService.writeFeed(result); 133 | break; 134 | case EMOTICON: 135 | messageService.sendEmoticon(result); 136 | break; 137 | case OUT: 138 | messageService.outRoom(result); 139 | break; 140 | } 141 | } 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/messenger/teamup/TeamUpEventSensor.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.messenger.teamup; 2 | 3 | import com.kingbbode.chatbot.autoconfigure.event.Event; 4 | import com.kingbbode.chatbot.autoconfigure.event.EventQueue; 5 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.response.EventResponse; 6 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.templates.template.EventTemplate; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 11 | import org.springframework.scheduling.annotation.EnableScheduling; 12 | import org.springframework.scheduling.annotation.Scheduled; 13 | import org.springframework.stereotype.Service; 14 | import org.springframework.util.ObjectUtils; 15 | 16 | import java.util.ArrayList; 17 | 18 | /** 19 | * Created by YG on 2016-03-28. 20 | */ 21 | @Service 22 | @EnableScheduling 23 | @ConditionalOnProperty(prefix = "chatbot.teamup", name = "enabled", havingValue = "true") 24 | public class TeamUpEventSensor { 25 | 26 | private static final Logger logger = LoggerFactory.getLogger( TeamUpEventSensor.class ); 27 | 28 | @Autowired 29 | private EventTemplate eventTemplate; 30 | 31 | @Autowired 32 | private EventQueue eventQueue; 33 | 34 | @Autowired 35 | private TeamUpDispatcher teamUpDispatcher; 36 | 37 | private boolean ready; 38 | 39 | public void setReady(boolean ready){ 40 | this.ready = ready; 41 | } 42 | 43 | @Scheduled(fixedDelay = 10) 44 | public void sensingEvent(){ 45 | if(ready) { 46 | EventResponse eventResponse = null; 47 | try { 48 | eventResponse = eventTemplate.getEvent(); 49 | } catch (Exception e) { 50 | logger.error("TeamUpEventSensor - sensingEvent : {}", e); 51 | } 52 | if (!ObjectUtils.isEmpty(eventResponse)) { 53 | ArrayList events = eventResponse.getEvents(); 54 | if (events != null && !events.isEmpty()) { 55 | events.forEach(event -> this.eventQueue.offer( 56 | new Event<>(teamUpDispatcher, event) 57 | )); 58 | } 59 | } 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/messenger/teamup/TeamUpMemberCached.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.messenger.teamup; 2 | 3 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.response.OrganigrammeResponse; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | /** 9 | * Created by YG on 2017-04-05. 10 | */ 11 | public class TeamUpMemberCached { 12 | //id,name 13 | private Map members; 14 | 15 | public void updateMember(OrganigrammeResponse organigramme){ 16 | Map tmpMembers = new HashMap<>(); 17 | organigramme.getDepartment() 18 | .forEach(department -> findUsers(department, tmpMembers)); 19 | members = tmpMembers; 20 | } 21 | 22 | private void findUsers(OrganigrammeResponse.Department department, Map tmpMembers){ 23 | if(department == null){ 24 | return; 25 | } 26 | if(department.getUsers() != null) { 27 | department.getUsers().forEach(user -> user.takeInfo(tmpMembers)); 28 | } 29 | if(department.getDepartment() != null){ 30 | department.getDepartment().forEach(department1 -> findUsers(department1, tmpMembers)); 31 | } 32 | } 33 | 34 | public String getMemberName(Long id){ 35 | return members.get(id); 36 | } 37 | 38 | public boolean containsMember(Long id){ 39 | return members.containsKey(id); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/messenger/teamup/TeamUpMemberService.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.messenger.teamup; 2 | 3 | import com.kingbbode.chatbot.autoconfigure.common.interfaces.MemberService; 4 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.response.OrganigrammeResponse; 5 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.response.RoomInfoResponse; 6 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.templates.template.AuthTemplate; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.transaction.annotation.Transactional; 9 | 10 | import javax.annotation.PostConstruct; 11 | 12 | /** 13 | * Created by YG on 2017-03-31. 14 | */ 15 | @Transactional 16 | public class TeamUpMemberService implements MemberService { 17 | 18 | @Autowired 19 | private TeamUpMemberCached memberCached; 20 | 21 | @Autowired 22 | private AuthTemplate authTemplate; 23 | 24 | @PostConstruct 25 | @Override 26 | public void update(){ 27 | OrganigrammeResponse response = authTemplate.readOrganigramme(); 28 | if(response == null || response.getDepartment() == null){ 29 | return; 30 | } 31 | memberCached.updateMember(response); 32 | } 33 | 34 | @Override 35 | public String get(String memberId){ 36 | return memberCached.getMemberName(Long.valueOf(memberId)); 37 | } 38 | 39 | @Override 40 | public boolean contains(String memberId){ 41 | if(!memberCached.containsMember(Long.valueOf(memberId))){ 42 | update(); 43 | } 44 | return memberCached.containsMember(Long.valueOf(memberId)); 45 | } 46 | 47 | @Override 48 | public RoomInfoResponse getRoomInfo(String room) { 49 | return authTemplate.getMembersInRoom(room); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/messenger/teamup/TeamUpTokenManager.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.messenger.teamup; 2 | 3 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.oauth2.OAuth2Token; 4 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.templates.template.Oauth2Template; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | 9 | import javax.annotation.PostConstruct; 10 | 11 | /** 12 | * Created by YG on 2016-05-11. 13 | */ 14 | public class TeamUpTokenManager { 15 | private final Logger logger = LoggerFactory.getLogger(this.getClass()); 16 | 17 | @Autowired 18 | TeamUpEventSensor teamUpEventSensor; 19 | 20 | private OAuth2Token token; 21 | 22 | @Autowired 23 | Oauth2Template oauth2Template; 24 | 25 | @PostConstruct 26 | void init(){ 27 | token = oauth2Template.token(token); 28 | if(token !=null && token.getAccessToken()!= null && !"".equals(token.getAccessToken())) { 29 | teamUpEventSensor.setReady(true); 30 | }else{ 31 | logger.error("Authentication Failed"); 32 | System.exit(0); 33 | } 34 | } 35 | 36 | public String getAccessToken() { 37 | token = oauth2Template.token(token); 38 | return token.getAccessToken(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/messenger/teamup/message/MessageService.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.messenger.teamup.message; 2 | 3 | import com.kingbbode.chatbot.autoconfigure.common.result.BrainResult; 4 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.request.FileRequest; 5 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.response.EventResponse; 6 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.response.FileUploadResponse; 7 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.response.MessageResponse; 8 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.response.RoomCreateResponse; 9 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.templates.template.EdgeTemplate; 10 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.templates.template.FileTemplate; 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.util.ObjectUtils; 15 | 16 | /** 17 | * Created by YG on 2016-03-28. 18 | */ 19 | public class MessageService { 20 | 21 | private static final Logger logger = LoggerFactory.getLogger(MessageService.class); 22 | 23 | @Autowired 24 | private EdgeTemplate edgeTemplate; 25 | 26 | @Autowired 27 | private FileTemplate fileTemplate; 28 | 29 | /*public String excuteMessageForChat(String content, String command) { 30 | return getMessageResult("999999999999", "8170", content, command); 31 | }*/ 32 | 33 | public MessageResponse.Message readMessage(EventResponse.Event.Chat chat) { 34 | MessageResponse readResponse = edgeTemplate.readMessage(chat.getMsg(), chat.getRoom()); 35 | if (!ObjectUtils.isEmpty(readResponse) && readResponse.getMsgs().size() > 0) { 36 | return readResponse.getMsgs().get(0); 37 | } 38 | return null; 39 | } 40 | 41 | public void sendMessage(BrainResult result) { 42 | edgeTemplate.sendMessage(result.getMessage(), result.getRoom()); 43 | } 44 | 45 | public RoomCreateResponse openRoom(BrainResult result) { 46 | return edgeTemplate.openRoom(result.getMessage()); 47 | } 48 | 49 | public void sendEmoticon(BrainResult result) { 50 | edgeTemplate.sendEmoticon(result.getMessage(), result.getRoom()); 51 | } 52 | 53 | public void writeFeed(BrainResult result) { 54 | edgeTemplate.writeFeed(result.getMessage(), result.getRoom()); 55 | } 56 | 57 | public FileUploadResponse writeImage(FileRequest fileRequest) { 58 | byte[] bytes = fileTemplate.download(fileRequest); 59 | if(bytes == null){ 60 | return null; 61 | } 62 | return fileTemplate.upload(fileRequest, bytes); 63 | } 64 | 65 | public void outRoom(BrainResult result) { 66 | edgeTemplate.sendMessage(result.getMessage(), result.getRoom()); 67 | try { 68 | Thread.sleep(500); 69 | } catch (InterruptedException e) { 70 | logger.warn("InterruptedException"); 71 | } 72 | edgeTemplate.outRoom(result.getRoom()); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/messenger/teamup/oauth2/OAuth2Token.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.messenger.teamup.oauth2; 2 | 3 | import java.util.Date; 4 | 5 | /** 6 | * Created by YG on 2017-02-07. 7 | */ 8 | public class OAuth2Token { 9 | 10 | public OAuth2Token() { 11 | } 12 | 13 | public OAuth2Token(String access_token, long expires_in, String token_type, String refresh_token){ 14 | this.access_token = access_token; 15 | this.expires_in = expires_in; 16 | this.token_type = token_type; 17 | this.refresh_token = refresh_token; 18 | } 19 | 20 | private String access_token; 21 | 22 | private long expires_in; 23 | 24 | private String token_type; 25 | 26 | private String refresh_token; 27 | 28 | public void setAccess_token(String access_token) { 29 | this.access_token = access_token; 30 | } 31 | 32 | public void setExpires_in(long expires_in) { 33 | this.expires_in = System.currentTimeMillis() + expires_in; 34 | } 35 | 36 | public void setToken_type(String token_type) { 37 | this.token_type = token_type; 38 | } 39 | 40 | public void setRefresh_token(String refresh_token) { 41 | this.refresh_token = refresh_token; 42 | } 43 | 44 | public String getAccessToken() { 45 | return token_type + " " + access_token; 46 | } 47 | 48 | public String getRefreshToken() { 49 | return refresh_token; 50 | } 51 | 52 | public boolean isExpired(){ 53 | return new Date(this.expires_in).before(new Date()); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/messenger/teamup/request/FileRequest.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.messenger.teamup.request; 2 | 3 | import com.kingbbode.chatbot.autoconfigure.common.request.BrainRequest; 4 | import org.springframework.http.MediaType; 5 | 6 | /** 7 | * Created by YG on 2017-05-17. 8 | */ 9 | public class FileRequest { 10 | private String messageNo; 11 | private String fileId; 12 | private String team; 13 | private String fileName; 14 | private MediaType type; 15 | 16 | private FileRequest(String messageNo, String fileId, String team, String fileName, MediaType type) { 17 | this.messageNo = messageNo; 18 | this.fileId = fileId; 19 | this.team = team; 20 | this.fileName = fileName; 21 | this.type = type; 22 | } 23 | 24 | public String getMessageNo() { 25 | return messageNo; 26 | } 27 | 28 | public String getFileId() { 29 | return fileId; 30 | } 31 | 32 | public String getTeam() { 33 | return team; 34 | } 35 | 36 | public String getFileName() { 37 | return fileName; 38 | } 39 | 40 | public MediaType getType() { 41 | return type; 42 | } 43 | 44 | public String getParam(){ 45 | return team + "/" + fileId + "?msg=" + messageNo; 46 | } 47 | 48 | public static class Builder { 49 | private String messageNo; 50 | private String fileId; 51 | private String team; 52 | private String fileName; 53 | private MediaType type; 54 | 55 | public Builder request(BrainRequest request){ 56 | this.messageNo = request.getMessageNo(); 57 | this.team = request.getTeam(); 58 | return this; 59 | } 60 | 61 | public Builder id(String fileId){ 62 | this.fileId = fileId; 63 | return this; 64 | } 65 | 66 | public Builder type(MediaType type){ 67 | this.type = type; 68 | return this; 69 | } 70 | 71 | public Builder name(String fileName){ 72 | this.fileName = System.currentTimeMillis() + fileName; 73 | return this; 74 | } 75 | 76 | public FileRequest build(){ 77 | return new FileRequest(messageNo, fileId, team, fileName, type); 78 | } 79 | 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/messenger/teamup/request/MessageRequest.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.messenger.teamup.request; 2 | 3 | /** 4 | * Created by YG on 2016-03-28. 5 | */ 6 | public class MessageRequest { 7 | public MessageRequest(String content) { 8 | this.content = content; 9 | } 10 | 11 | private String content; 12 | 13 | public String getContent() { 14 | return content; 15 | } 16 | 17 | public void setContent(String content) { 18 | this.content = content; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/messenger/teamup/request/RoomCreateRequest.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.messenger.teamup.request; 2 | 3 | /** 4 | * Created by YG on 2017-07-21. 5 | */ 6 | public class RoomCreateRequest { 7 | public RoomCreateRequest(int[] users) { 8 | this.users = users; 9 | } 10 | 11 | private int[] users; 12 | 13 | public int[] getUsers() { 14 | return users; 15 | } 16 | 17 | public void setUsers(int[] users) { 18 | this.users = users; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/messenger/teamup/response/EventResponse.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.messenger.teamup.response; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | 5 | import java.util.ArrayList; 6 | 7 | /** 8 | * Created by YG on 2016-03-28. 9 | */ 10 | @JsonIgnoreProperties(ignoreUnknown = true) 11 | public class EventResponse { 12 | private ArrayList events; 13 | 14 | public ArrayList getEvents() { 15 | return events; 16 | } 17 | 18 | public void setEvents(ArrayList events) { 19 | this.events = events; 20 | } 21 | 22 | @JsonIgnoreProperties(ignoreUnknown = true) 23 | public static class Event{ 24 | private String type; 25 | private Chat chat; 26 | private Feed feed; 27 | private Inform inform; 28 | 29 | public String getType() { 30 | return type; 31 | } 32 | 33 | public void setType(String type) { 34 | this.type = type; 35 | } 36 | 37 | public Chat getChat() { 38 | return chat; 39 | } 40 | 41 | public void setChat(Chat chat) { 42 | this.chat = chat; 43 | } 44 | 45 | public Feed getFeed() { 46 | return feed; 47 | } 48 | 49 | public void setFeed(Feed feed) { 50 | this.feed = feed; 51 | } 52 | 53 | public Inform getInform() { 54 | return inform; 55 | } 56 | 57 | public void setInform(Inform inform) { 58 | this.inform = inform; 59 | } 60 | 61 | @JsonIgnoreProperties(ignoreUnknown = true) 62 | public static class Chat{ 63 | private String team; 64 | private String room; 65 | private String msg; 66 | private String user; 67 | 68 | public String getTeam() { 69 | return team; 70 | } 71 | 72 | public void setTeam(String team) { 73 | this.team = team; 74 | } 75 | 76 | public String getRoom() { 77 | return room; 78 | } 79 | 80 | public void setRoom(String room) { 81 | this.room = room; 82 | } 83 | 84 | public String getMsg() { 85 | return msg; 86 | } 87 | 88 | public void setMsg(String msg) { 89 | this.msg = msg; 90 | } 91 | 92 | public String getUser() { 93 | return user; 94 | } 95 | 96 | public void setUser(String user) { 97 | this.user = user; 98 | } 99 | } 100 | 101 | @JsonIgnoreProperties(ignoreUnknown = true) 102 | public static class Feed{ 103 | private String feedgroup; 104 | 105 | public String getFeedgroup() { 106 | return feedgroup; 107 | } 108 | 109 | public void setFeedgroup(String feedgroup) { 110 | this.feedgroup = feedgroup; 111 | } 112 | } 113 | 114 | @JsonIgnoreProperties(ignoreUnknown = true) 115 | public static class Inform{ 116 | private String feedgroup; 117 | 118 | public String getFeedgroup() { 119 | return feedgroup; 120 | } 121 | 122 | public void setFeedgroup(String feedgroup) { 123 | this.feedgroup = feedgroup; 124 | } 125 | } 126 | } 127 | 128 | } 129 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/messenger/teamup/response/FeedGroupsResponse.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.messenger.teamup.response; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * Created by YG on 2017-04-05. 9 | */ 10 | @JsonIgnoreProperties(ignoreUnknown = true) 11 | public class FeedGroupsResponse { 12 | 13 | private List feedgroups; 14 | 15 | public List getFeedgroups() { 16 | return feedgroups; 17 | } 18 | 19 | public void setFeedgroups(List feedgroups) { 20 | this.feedgroups = feedgroups; 21 | } 22 | 23 | @JsonIgnoreProperties(ignoreUnknown = true) 24 | public static class FeedGroup { 25 | private Integer team; 26 | private Long feedgroup; 27 | private String groupname; 28 | private Integer watchfeed; 29 | private Integer writable; 30 | private Integer alerttype; 31 | private Integer alertfeed; 32 | private Integer alertreply; 33 | private Integer star; 34 | 35 | public Integer getTeam() { 36 | return team; 37 | } 38 | 39 | public void setTeam(Integer team) { 40 | this.team = team; 41 | } 42 | 43 | public Long getFeedgroup() { 44 | return feedgroup; 45 | } 46 | 47 | public void setFeedgroup(Long feedgroup) { 48 | this.feedgroup = feedgroup; 49 | } 50 | 51 | public String getGroupname() { 52 | return groupname; 53 | } 54 | 55 | public void setGroupname(String groupname) { 56 | this.groupname = groupname; 57 | } 58 | 59 | public Integer getWatchfeed() { 60 | return watchfeed; 61 | } 62 | 63 | public void setWatchfeed(Integer watchfeed) { 64 | this.watchfeed = watchfeed; 65 | } 66 | 67 | public Integer getWritable() { 68 | return writable; 69 | } 70 | 71 | public void setWritable(Integer writable) { 72 | this.writable = writable; 73 | } 74 | 75 | public Integer getAlerttype() { 76 | return alerttype; 77 | } 78 | 79 | public void setAlerttype(Integer alerttype) { 80 | this.alerttype = alerttype; 81 | } 82 | 83 | public Integer getAlertfeed() { 84 | return alertfeed; 85 | } 86 | 87 | public void setAlertfeed(Integer alertfeed) { 88 | this.alertfeed = alertfeed; 89 | } 90 | 91 | public Integer getAlertreply() { 92 | return alertreply; 93 | } 94 | 95 | public void setAlertreply(Integer alertreply) { 96 | this.alertreply = alertreply; 97 | } 98 | 99 | public Integer getStar() { 100 | return star; 101 | } 102 | 103 | public void setStar(Integer star) { 104 | this.star = star; 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/messenger/teamup/response/FileUploadResponse.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.messenger.teamup.response; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * Created by YG on 2017-05-17. 9 | */ 10 | @JsonIgnoreProperties(ignoreUnknown = true) 11 | public class FileUploadResponse { 12 | 13 | public FileUploadResponse() { 14 | } 15 | 16 | public FileUploadResponse(List files) { 17 | this.files = files; 18 | } 19 | 20 | private List files; 21 | 22 | public List getFiles() { 23 | return files; 24 | } 25 | 26 | public void setFiles(List files) { 27 | this.files = files; 28 | } 29 | 30 | @JsonIgnoreProperties(ignoreUnknown = true) 31 | public static class File { 32 | public File() { 33 | } 34 | 35 | public File(String name, String id) { 36 | this.name = name; 37 | this.id = id; 38 | } 39 | 40 | private String name; 41 | private String id; 42 | 43 | public String getName() { 44 | return name; 45 | } 46 | 47 | public String getId() { 48 | return id; 49 | } 50 | 51 | public void setId(String id) { 52 | this.id = id; 53 | } 54 | 55 | public void setName(String name) { 56 | this.name = name; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/messenger/teamup/response/MessageResponse.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.messenger.teamup.response; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | 5 | import java.util.Arrays; 6 | import java.util.List; 7 | 8 | /** 9 | * Created by YG on 2016-09-12. 10 | */ 11 | @JsonIgnoreProperties(ignoreUnknown = true) 12 | public class MessageResponse { 13 | List msgs; 14 | 15 | public List getMsgs() { 16 | return msgs; 17 | } 18 | 19 | public void setMsgs(List msgs) { 20 | this.msgs = msgs; 21 | } 22 | 23 | @JsonIgnoreProperties(ignoreUnknown = true) 24 | public static class Message{ 25 | 26 | int msg; 27 | 28 | int user; 29 | 30 | int type; 31 | 32 | int len; 33 | 34 | String content; 35 | 36 | long created; 37 | 38 | String tagfeeds; 39 | 40 | int[] users; 41 | 42 | File file; 43 | 44 | public int getMsg() { 45 | return msg; 46 | } 47 | 48 | public void setMsg(int msg) { 49 | this.msg = msg; 50 | } 51 | 52 | public int getUser() { 53 | return user; 54 | } 55 | 56 | public void setUser(int user) { 57 | this.user = user; 58 | } 59 | 60 | public int getType() { 61 | return type; 62 | } 63 | 64 | public void setType(int type) { 65 | this.type = type; 66 | } 67 | 68 | public int getLen() { 69 | return len; 70 | } 71 | 72 | public void setLen(int len) { 73 | this.len = len; 74 | } 75 | 76 | public String getContent() { 77 | return content; 78 | } 79 | 80 | public void setContent(String content) { 81 | this.content = content; 82 | } 83 | 84 | public long getCreated() { 85 | return created; 86 | } 87 | 88 | public void setCreated(long created) { 89 | this.created = created; 90 | } 91 | 92 | public String getTagfeeds() { 93 | return tagfeeds; 94 | } 95 | 96 | public void setTagfeeds(String tagfeeds) { 97 | this.tagfeeds = tagfeeds; 98 | } 99 | 100 | public int[] getUsers() { 101 | return users==null?null:Arrays.copyOf(users, users.length); 102 | } 103 | 104 | public void setUsers(int[] users) { 105 | this.users = users==null?null:Arrays.copyOf(users, users.length); 106 | } 107 | 108 | public File getFile() { 109 | return file; 110 | } 111 | 112 | public void setFile(File file) { 113 | this.file = file; 114 | } 115 | } 116 | 117 | @JsonIgnoreProperties(ignoreUnknown = true) 118 | public static class File{ 119 | String name; 120 | 121 | int size; 122 | 123 | String id; 124 | 125 | int owner; 126 | 127 | String type; 128 | 129 | public String getName() { 130 | return name; 131 | } 132 | 133 | public void setName(String name) { 134 | this.name = name; 135 | } 136 | 137 | public int getSize() { 138 | return size; 139 | } 140 | 141 | public void setSize(int size) { 142 | this.size = size; 143 | } 144 | 145 | public String getId() { 146 | return id; 147 | } 148 | 149 | public void setId(String id) { 150 | this.id = id; 151 | } 152 | 153 | public int getOwner() { 154 | return owner; 155 | } 156 | 157 | public void setOwner(int owner) { 158 | this.owner = owner; 159 | } 160 | 161 | public String getType() { 162 | return type; 163 | } 164 | 165 | public void setType(String type) { 166 | this.type = type; 167 | } 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/messenger/teamup/response/OrganigrammeResponse.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.messenger.teamup.response; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | /** 9 | * Created by YG on 2017-05-18. 10 | */ 11 | @JsonIgnoreProperties(ignoreUnknown = true) 12 | public class OrganigrammeResponse { 13 | private int index; 14 | private String name; 15 | private List users; 16 | private List department; 17 | 18 | public List getUsers() { 19 | return users; 20 | } 21 | 22 | public void setUsers(List users) { 23 | this.users = users; 24 | } 25 | 26 | public int getIndex() { 27 | return index; 28 | } 29 | 30 | public void setIndex(int index) { 31 | this.index = index; 32 | } 33 | 34 | public String getName() { 35 | return name; 36 | } 37 | 38 | public void setName(String name) { 39 | this.name = name; 40 | } 41 | 42 | public List getDepartment() { 43 | return department; 44 | } 45 | 46 | public void setDepartment(List department) { 47 | this.department = department; 48 | } 49 | 50 | @JsonIgnoreProperties(ignoreUnknown = true) 51 | public static class User { 52 | private long index; 53 | private String name; 54 | 55 | public long getIndex() { 56 | return index; 57 | } 58 | 59 | public void setIndex(long index) { 60 | this.index = index; 61 | } 62 | 63 | public String getName() { 64 | return name; 65 | } 66 | 67 | public void setName(String name) { 68 | this.name = name; 69 | } 70 | 71 | public void takeInfo(Map tmpMembers){ 72 | tmpMembers.put(index,name); 73 | } 74 | } 75 | 76 | @JsonIgnoreProperties(ignoreUnknown = true) 77 | public static class Department { 78 | private int index; 79 | private String name; 80 | private List users; 81 | private List department; 82 | 83 | public int getIndex() { 84 | return index; 85 | } 86 | 87 | public void setIndex(int index) { 88 | this.index = index; 89 | } 90 | 91 | public String getName() { 92 | return name; 93 | } 94 | 95 | public void setName(String name) { 96 | this.name = name; 97 | } 98 | 99 | public List getUsers() { 100 | return users; 101 | } 102 | 103 | public void setUsers(List users) { 104 | this.users = users; 105 | } 106 | 107 | public List getDepartment() { 108 | return department; 109 | } 110 | 111 | public void setDepartment(List department) { 112 | this.department = department; 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/messenger/teamup/response/RefreshResponse.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.messenger.teamup.response; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | 5 | /** 6 | * Created by YG on 2016-03-28. 7 | */ 8 | @JsonIgnoreProperties(ignoreUnknown = true) 9 | public class RefreshResponse { 10 | private String access_token; 11 | private Integer expires_in; 12 | private String token_type; 13 | private String refresh_token; 14 | 15 | public String getAccess_token() { 16 | return access_token; 17 | } 18 | 19 | public void setAccess_token(String access_token) { 20 | this.access_token = access_token; 21 | } 22 | 23 | public String getToken_type() { 24 | return token_type; 25 | } 26 | 27 | public void setToken_type(String token_type) { 28 | this.token_type = token_type; 29 | } 30 | 31 | public String getRefresh_token() { 32 | return refresh_token; 33 | } 34 | 35 | public void setRefresh_token(String refresh_token) { 36 | this.refresh_token = refresh_token; 37 | } 38 | 39 | public Integer getExpires_in() { 40 | return expires_in; 41 | } 42 | 43 | public void setExpires_in(Integer expires_in) { 44 | this.expires_in = expires_in; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/messenger/teamup/response/RoomCreateResponse.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.messenger.teamup.response; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | 7 | /** 8 | * Created by YG on 2017-07-21. 9 | */ 10 | @JsonIgnoreProperties(ignoreUnknown = true) 11 | @Getter 12 | @Setter 13 | public class RoomCreateResponse { 14 | private Integer room; 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/messenger/teamup/response/RoomInfoResponse.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.messenger.teamup.response; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | 5 | import java.util.Random; 6 | 7 | /** 8 | * Created by jeonghoon on 2017-06-01. 9 | */ 10 | @JsonIgnoreProperties(ignoreUnknown = true) 11 | public class RoomInfoResponse { 12 | 13 | int[] users; 14 | 15 | public int[] getUsers() { 16 | return users; 17 | } 18 | 19 | public void setUsers(int[] users) { 20 | this.users = users; 21 | } 22 | 23 | public String pickMe() { 24 | return String.valueOf(this.users[new Random().nextInt(users.length)]); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/messenger/teamup/templates/BaseTemplate.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.messenger.teamup.templates; 2 | 3 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.TeamUpTokenManager; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.core.ParameterizedTypeReference; 8 | import org.springframework.http.*; 9 | import org.springframework.web.client.HttpClientErrorException; 10 | import org.springframework.web.client.ResourceAccessException; 11 | import org.springframework.web.client.RestClientException; 12 | import org.springframework.web.client.RestOperations; 13 | 14 | import java.net.SocketTimeoutException; 15 | 16 | /** 17 | * Created by YG on 2016-10-13. 18 | */ 19 | public class BaseTemplate { 20 | private static final Logger logger = LoggerFactory.getLogger(BaseTemplate.class); 21 | 22 | @Autowired 23 | private TeamUpTokenManager tokenManager; 24 | 25 | private RestOperations restOperations; 26 | 27 | public void setRestOperations(RestOperations restOperations) { 28 | this.restOperations = restOperations; 29 | } 30 | 31 | protected T get(String url, ParameterizedTypeReference p) { 32 | return send(url, null, p, HttpMethod.GET); 33 | } 34 | 35 | protected T post(String url, Object request, ParameterizedTypeReference p) { 36 | return send(url, request, p, HttpMethod.POST); 37 | } 38 | 39 | protected T delete(String url, Object request, ParameterizedTypeReference p) { 40 | return send(url, request, p, HttpMethod.DELETE); 41 | } 42 | 43 | private T send(String url, Object request, ParameterizedTypeReference p, HttpMethod httpMethod) { 44 | 45 | HttpEntity entity = getEntity(request); 46 | ResponseEntity responseEntity = null; 47 | 48 | try { 49 | responseEntity = restOperations.exchange(url, httpMethod, entity, p); 50 | } catch (ResourceAccessException e) { 51 | Throwable t = e.getCause(); 52 | if (t != null && !(t instanceof SocketTimeoutException)) { 53 | logger.error("ResourceAccessException - {}", e); 54 | } 55 | }catch (HttpClientErrorException e){ 56 | logger.error("HttpClientErrorException - {}", e); 57 | } catch (RestClientException e) { 58 | logger.error(url, e); 59 | } 60 | catch (Exception e) { 61 | logger.error("url", e); 62 | } 63 | 64 | if (responseEntity != null && responseEntity.getStatusCode().equals(HttpStatus.OK)) { 65 | return responseEntity.getBody(); 66 | } else { 67 | if(responseEntity != null){ 68 | logger.error("StatusCode : " + responseEntity.getStatusCode()); 69 | } 70 | } 71 | return null; 72 | } 73 | 74 | protected HttpEntity getEntity(Object request) { 75 | HttpHeaders headers = new HttpHeaders(); 76 | headers.setContentType(MediaType.APPLICATION_JSON); 77 | headers.add("Authorization", tokenManager.getAccessToken()); 78 | return new HttpEntity<>(request, headers); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/messenger/teamup/templates/template/AuthTemplate.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.messenger.teamup.templates.template; 2 | 3 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.Api; 4 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.response.OrganigrammeResponse; 5 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.response.RoomInfoResponse; 6 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.templates.BaseTemplate; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.beans.factory.annotation.Qualifier; 9 | import org.springframework.core.ParameterizedTypeReference; 10 | import org.springframework.web.client.RestOperations; 11 | 12 | import javax.annotation.PostConstruct; 13 | 14 | /** 15 | * Created by YG on 2017-05-18. 16 | */ 17 | public class AuthTemplate extends BaseTemplate { 18 | 19 | @Autowired 20 | @Qualifier(value = "messageRestOperations") 21 | private RestOperations restOperations; 22 | 23 | @PostConstruct 24 | void init(){ 25 | super.setRestOperations(restOperations); 26 | } 27 | 28 | public OrganigrammeResponse readOrganigramme() { 29 | ParameterizedTypeReference p = new ParameterizedTypeReference() { 30 | }; 31 | return get(Api.AUTH_ORGANIGRAMME.getUrl() + "1/all", p); 32 | } 33 | 34 | public RoomInfoResponse getMembersInRoom(String room) { 35 | ParameterizedTypeReference r = new ParameterizedTypeReference() { 36 | }; 37 | return get(Api.ROOM.getUrl() + room, r); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/messenger/teamup/templates/template/EdgeTemplate.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.messenger.teamup.templates.template; 2 | 3 | import com.kingbbode.chatbot.autoconfigure.TeamUpProperties; 4 | import com.kingbbode.chatbot.autoconfigure.common.properties.BotProperties; 5 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.Api; 6 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.request.MessageRequest; 7 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.request.RoomCreateRequest; 8 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.response.FeedGroupsResponse; 9 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.response.MessageResponse; 10 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.response.RoomCreateResponse; 11 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.templates.BaseTemplate; 12 | import org.apache.commons.lang3.StringUtils; 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.beans.factory.annotation.Qualifier; 15 | import org.springframework.core.ParameterizedTypeReference; 16 | import org.springframework.scheduling.annotation.Async; 17 | import org.springframework.web.client.RestOperations; 18 | 19 | import javax.annotation.PostConstruct; 20 | 21 | /** 22 | * Created by YG on 2016-10-13. 23 | */ 24 | public class EdgeTemplate extends BaseTemplate { 25 | 26 | @Autowired 27 | private BotProperties botProperties; 28 | 29 | @Autowired 30 | private TeamUpProperties teamUpProperties; 31 | 32 | @Autowired 33 | @Qualifier(value = "messageRestOperations") 34 | private RestOperations restOperations; 35 | 36 | @PostConstruct 37 | void init(){ 38 | super.setRestOperations(restOperations); 39 | } 40 | 41 | @Async 42 | public MessageResponse readMessage(String message, String room) { 43 | ParameterizedTypeReference p = new ParameterizedTypeReference() { 44 | }; 45 | return get(Api.MESSAGE_READ.getUrl() + room + "/1/0/" + message, p); 46 | 47 | } 48 | 49 | @Async 50 | public void sendMessage(String message, String room) { 51 | if(!room.equals("999999999999") && !StringUtils.isEmpty(message)) { 52 | ParameterizedTypeReference p = new ParameterizedTypeReference() { 53 | }; 54 | post(Api.MESSAGE_SEND.getUrl() + (botProperties.isTestMode()?teamUpProperties.getTestRoom():room), new MessageRequest(message), p); 55 | } 56 | } 57 | 58 | @Async 59 | public RoomCreateResponse openRoom(String userId) { 60 | ParameterizedTypeReference p = new ParameterizedTypeReference() { 61 | }; 62 | return post(Api.ROOM.getUrl() + "1", new RoomCreateRequest(new int[]{Integer.parseInt(botProperties.isTestMode()?teamUpProperties.getTestUser():userId)}), p); 63 | } 64 | 65 | @Async 66 | public void writeFeed(String message, String room) { 67 | ParameterizedTypeReference p = new ParameterizedTypeReference() { 68 | }; 69 | post(Api.FEED_WRITE.getUrl() + (botProperties.isTestMode()?teamUpProperties.getTestFeed():room),new MessageRequest(message), p); 70 | } 71 | 72 | @Async 73 | public void sendEmoticon(String fileId, String room) { 74 | if(!room.equals("999999999999") && !StringUtils.isEmpty(fileId)) { 75 | ParameterizedTypeReference p = new ParameterizedTypeReference() { 76 | }; 77 | post(Api.MESSAGE_SEND.getUrl() + (botProperties.isTestMode()?teamUpProperties.getTestRoom():room) +"/2", new MessageRequest(fileId), p); 78 | } 79 | } 80 | 81 | public void outRoom(String room) { 82 | if(!room.equals("999999999999") && !StringUtils.isEmpty(room)) { 83 | ParameterizedTypeReference p = new ParameterizedTypeReference() { 84 | }; 85 | delete(Api.ROOM.getUrl() + "/" + room + "/" + System.currentTimeMillis() + room, null, p); 86 | } 87 | } 88 | 89 | public FeedGroupsResponse readFeedGroupList(){ 90 | ParameterizedTypeReference p = new ParameterizedTypeReference() { 91 | }; 92 | return get(Api.FEED_LIST.getUrl(), p); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/messenger/teamup/templates/template/EventTemplate.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.messenger.teamup.templates.template; 2 | 3 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.Api; 4 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.response.EventResponse; 5 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.templates.BaseTemplate; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.beans.factory.annotation.Qualifier; 8 | import org.springframework.core.ParameterizedTypeReference; 9 | import org.springframework.web.client.RestOperations; 10 | 11 | import javax.annotation.PostConstruct; 12 | 13 | /** 14 | * Created by YG on 2016-10-13. 15 | */ 16 | public class EventTemplate extends BaseTemplate { 17 | 18 | 19 | @Autowired 20 | @Qualifier(value = "eventRestOperations") 21 | RestOperations restOperations; 22 | 23 | @PostConstruct 24 | void init(){ 25 | super.setRestOperations(restOperations); 26 | } 27 | 28 | public EventResponse getEvent() { 29 | ParameterizedTypeReference p = new ParameterizedTypeReference() { 30 | }; 31 | return get(Api.RTM.getUrl(), p); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/messenger/teamup/templates/template/FileTemplate.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.messenger.teamup.templates.template; 2 | 3 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.Api; 4 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.TeamUpTokenManager; 5 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.request.FileRequest; 6 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.response.FileUploadResponse; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.beans.factory.annotation.Qualifier; 11 | import org.springframework.core.io.ByteArrayResource; 12 | import org.springframework.http.*; 13 | import org.springframework.util.LinkedMultiValueMap; 14 | import org.springframework.util.MultiValueMap; 15 | import org.springframework.web.client.HttpClientErrorException; 16 | import org.springframework.web.client.ResourceAccessException; 17 | import org.springframework.web.client.RestClientException; 18 | import org.springframework.web.client.RestOperations; 19 | 20 | import java.net.SocketTimeoutException; 21 | 22 | /** 23 | * Created by YG on 2017-05-17. 24 | */ 25 | public class FileTemplate { 26 | private final Logger logger = LoggerFactory.getLogger(this.getClass()); 27 | @Autowired 28 | @Qualifier(value = "fileRestOperations") 29 | private RestOperations restOperations; 30 | 31 | 32 | @Autowired 33 | TeamUpTokenManager tokenManager; 34 | 35 | public byte[] download(FileRequest fileRequest) { 36 | HttpHeaders headers = new HttpHeaders(); 37 | headers.add("Authorization", tokenManager.getAccessToken()); 38 | HttpEntity entity = new HttpEntity<>(null, headers); 39 | ResponseEntity responseEntity = null; 40 | 41 | try { 42 | responseEntity = restOperations.exchange(Api.FILE_DOWNLOAD.getUrl() + fileRequest.getParam(), HttpMethod.GET, entity, byte[].class); 43 | } catch (ResourceAccessException e) { 44 | Throwable t = e.getCause(); 45 | if (t != null && !(t instanceof SocketTimeoutException)) { 46 | logger.error("ResourceAccessException - {}", e); 47 | } 48 | }catch (HttpClientErrorException e){ 49 | logger.error("HttpClientErrorException - {}", e); 50 | } catch (RestClientException e) { 51 | logger.error("download.." + fileRequest.getParam(), e); 52 | } 53 | catch (Exception e) { 54 | logger.error("url", e); 55 | } 56 | 57 | if (responseEntity != null && responseEntity.getStatusCode().equals(HttpStatus.OK)) { 58 | return responseEntity.getBody(); 59 | } else { 60 | if(responseEntity != null){ 61 | logger.error("StatusCode : " + responseEntity.getStatusCode()); 62 | } 63 | } 64 | return null; 65 | } 66 | 67 | public FileUploadResponse upload(FileRequest fileRequest, byte[] bytes) { 68 | ByteArrayResource image = new ByteArrayResource(bytes){ 69 | @Override 70 | public String getFilename(){ 71 | return fileRequest.getFileName(); 72 | } 73 | }; 74 | HttpHeaders header = new HttpHeaders(); 75 | header.setContentType(MediaType.MULTIPART_FORM_DATA); 76 | header.add("Authorization", tokenManager.getAccessToken()); 77 | 78 | MultiValueMap multipartRequest = new LinkedMultiValueMap<>(); 79 | HttpHeaders imageHeader = new HttpHeaders(); 80 | imageHeader.setContentType(fileRequest.getType()); 81 | HttpEntity imagePart = new HttpEntity<>(image, imageHeader); 82 | multipartRequest.add("files[]", imagePart); 83 | HttpEntity> entity = new HttpEntity<>(multipartRequest, header); 84 | ResponseEntity responseEntity = null; 85 | try { 86 | responseEntity = restOperations.exchange(Api.FILE_UPLOAD.getUrl() + fileRequest.getTeam(), HttpMethod.POST, entity, FileUploadResponse.class); 87 | } catch (ResourceAccessException e) { 88 | Throwable t = e.getCause(); 89 | if (t != null && !(t instanceof SocketTimeoutException)) { 90 | logger.error("ResourceAccessException - {}", e); 91 | } 92 | }catch (HttpClientErrorException e){ 93 | logger.error("HttpClientErrorException - {}", e); 94 | } catch (RestClientException e) { 95 | logger.error("upload.." + fileRequest.getTeam(), e); 96 | } 97 | catch (Exception e) { 98 | logger.error("url", e); 99 | } 100 | 101 | if (responseEntity != null && responseEntity.getStatusCode().equals(HttpStatus.OK)) { 102 | return responseEntity.getBody(); 103 | } else { 104 | if(responseEntity != null){ 105 | logger.error("StatusCode : " + responseEntity.getStatusCode()); 106 | } 107 | } 108 | return null; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/messenger/teamup/templates/template/Oauth2Template.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.messenger.teamup.templates.template; 2 | 3 | import com.kingbbode.chatbot.autoconfigure.TeamUpProperties; 4 | import com.kingbbode.chatbot.autoconfigure.common.enums.GrantType; 5 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.Api; 6 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.oauth2.OAuth2Token; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.beans.factory.annotation.Qualifier; 9 | import org.springframework.http.*; 10 | import org.springframework.util.LinkedMultiValueMap; 11 | import org.springframework.util.MultiValueMap; 12 | import org.springframework.web.client.RestOperations; 13 | 14 | /** 15 | * Created by YG on 2016-10-14. 16 | */ 17 | public class Oauth2Template { 18 | @Autowired 19 | @Qualifier(value = "messageRestOperations") 20 | private RestOperations restOperations; 21 | 22 | @Autowired 23 | private TeamUpProperties teamUpProperties; 24 | 25 | public OAuth2Token token(OAuth2Token token){ 26 | if (token == null) { 27 | return post(token, GrantType.PASSWORD); 28 | }else{ 29 | if (token.isExpired()) { 30 | return refresh(token); 31 | } 32 | } 33 | return token; 34 | } 35 | 36 | private OAuth2Token refresh(OAuth2Token token) { 37 | return post(token, GrantType.REFRESH); 38 | } 39 | 40 | private OAuth2Token post(OAuth2Token token, GrantType grantType) { 41 | ResponseEntity response = restOperations.postForEntity(Api.TOKEN.getUrl(), getEntity(token, grantType), 42 | OAuth2Token.class); 43 | 44 | if (response.getStatusCode().equals(HttpStatus.OK)) { 45 | token = response.getBody(); 46 | } 47 | 48 | return token; 49 | } 50 | 51 | 52 | private HttpEntity getEntity(OAuth2Token token, GrantType grantType) { 53 | HttpHeaders header = new HttpHeaders(); 54 | header.setContentType(MediaType.APPLICATION_FORM_URLENCODED); 55 | MultiValueMap data = new LinkedMultiValueMap<>(); 56 | data.add("grant_type", grantType.getKey()); 57 | if (GrantType.PASSWORD.equals(grantType)) { 58 | data.add("client_id", teamUpProperties.getClientId()); 59 | data.add("client_secret", teamUpProperties.getClientSecret()); 60 | data.add("username", teamUpProperties.getId()); 61 | data.add("password", teamUpProperties.getPassword()); 62 | } else if (GrantType.REFRESH.equals(grantType)) { 63 | data.add("refresh_token", token.getRefreshToken()); 64 | } 65 | return new HttpEntity<>(data, header); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/com/kingbbode/chatbot/autoconfigure/messenger/teamup/util/ImagesUtils.java: -------------------------------------------------------------------------------- 1 | package com.kingbbode.chatbot.autoconfigure.messenger.teamup.util; 2 | 3 | import com.kingbbode.chatbot.autoconfigure.messenger.teamup.response.MessageResponse; 4 | import org.springframework.http.MediaType; 5 | 6 | /** 7 | * Created by YG on 2017-05-17. 8 | */ 9 | public class ImagesUtils { 10 | private static final String IMAGE_PATTERN_REGEX = "([^(\\s|\\.)]+(\\.(?i)(jpg|png))$)"; 11 | 12 | public static boolean isImage(MessageResponse.File file) { 13 | return file.getName() != null && file.getName().matches(IMAGE_PATTERN_REGEX); 14 | } 15 | 16 | public static MediaType selectMediaTypeForImage(String fileName) { 17 | if("jpg".equals(fileName)){ 18 | return MediaType.IMAGE_JPEG; 19 | }else if("png".equals(fileName)){ 20 | return MediaType.IMAGE_PNG; 21 | } 22 | throw new NullPointerException(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | # Auto Configure 2 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ 3 | com.kingbbode.chatbot.autoconfigure.ChatbotAutoConfiguration --------------------------------------------------------------------------------