├── .gitignore ├── LICENSE ├── README.md ├── config ├── application.properties └── robot.properties ├── mvnw ├── mvnw.cmd ├── pom.xml └── src ├── lib ├── common-1.2.1.jar └── sdk-1.2.1.jar ├── main ├── java │ ├── cn │ │ └── wildfirechat │ │ │ └── app │ │ │ ├── Application.java │ │ │ ├── Controller.java │ │ │ ├── DESUtil.java │ │ │ ├── ExecutorConfig.java │ │ │ ├── HttpUtils.java │ │ │ ├── RobotConfig.java │ │ │ ├── Service.java │ │ │ ├── ServiceImpl.java │ │ │ ├── TokenUtils.java │ │ │ ├── tuling │ │ │ ├── TulingResponse.java │ │ │ └── TulingService.java │ │ │ └── webhook │ │ │ ├── IWebhook.java │ │ │ ├── WebhookService.java │ │ │ ├── general │ │ │ └── GeneralWebhook.java │ │ │ ├── gitee │ │ │ ├── GiteeWebhook.java │ │ │ └── pojo │ │ │ │ ├── Branch.java │ │ │ │ ├── Commit.java │ │ │ │ ├── Enterprise.java │ │ │ │ ├── Issue.java │ │ │ │ ├── IssueHook.java │ │ │ │ ├── Label.java │ │ │ │ ├── Milestone.java │ │ │ │ ├── Note.java │ │ │ │ ├── NoteHook.java │ │ │ │ ├── Project.java │ │ │ │ ├── PullRequest.java │ │ │ │ ├── PullRequestHook.java │ │ │ │ ├── PushOrTagHook.java │ │ │ │ └── User.java │ │ │ ├── github │ │ │ ├── GithubWebhook.java │ │ │ └── pojo │ │ │ │ ├── Comment.java │ │ │ │ ├── Commit.java │ │ │ │ ├── ForkEvent.java │ │ │ │ ├── Forkee.java │ │ │ │ ├── Issue.java │ │ │ │ ├── IssueCommentEvent.java │ │ │ │ ├── IssueEvent.java │ │ │ │ ├── License.java │ │ │ │ ├── PingEvent.java │ │ │ │ ├── PullRequest.java │ │ │ │ ├── PullRequestEvent.java │ │ │ │ ├── PushEvent.java │ │ │ │ ├── Pusher.java │ │ │ │ ├── Repository.java │ │ │ │ ├── Sender.java │ │ │ │ ├── StarEvent.java │ │ │ │ ├── User.java │ │ │ │ └── WatchEvent.java │ │ │ └── gitlab │ │ │ ├── GitLabWebhook.java │ │ │ └── pojo │ │ │ ├── Author.java │ │ │ ├── Commit.java │ │ │ ├── IssueEvent.java │ │ │ ├── IssueObjectAttributes.java │ │ │ ├── Label.java │ │ │ ├── MergeRequest.java │ │ │ ├── MergeRequestEvent.java │ │ │ ├── NoteEvent.java │ │ │ ├── NoteObjectAttributes.java │ │ │ ├── Project.java │ │ │ ├── PushEvent.java │ │ │ ├── Repository.java │ │ │ ├── Snippet.java │ │ │ ├── TagEvent.java │ │ │ └── User.java │ └── ikidou │ │ └── reflect │ │ ├── TypeBuilder.java │ │ ├── TypeToken.java │ │ ├── exception │ │ └── TypeException.java │ │ └── typeimpl │ │ ├── ParameterizedTypeImpl.java │ │ └── WildcardTypeImpl.java └── resources │ └── application.properties └── test └── java └── cn └── wildfirechat └── app └── ApplicationTests.java /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | .idea 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 wildfirechat 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | 1. ikidou/TypeBuilder 24 | Copyright 2016 ikidou 25 | 26 | Licensed under the Apache License, Version 2.0 (the "License"); 27 | you may not use this file except in compliance with the License. 28 | You may obtain a copy of the License at 29 | 30 | http://www.apache.org/licenses/LICENSE-2.0 31 | 32 | Unless required by applicable law or agreed to in writing, software 33 | distributed under the License is distributed on an "AS IS" BASIS, 34 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 35 | See the License for the specific language governing permissions and 36 | limitations under the License. 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 野火IM机器人应用 2 | 作为野火IM机器人应用的演示,本工程仅演示机器人应用的接口。其中用到图灵的免费版。 3 | 4 | #### 编译 5 | ``` 6 | mvn package 7 | ``` 8 | 9 | #### 图灵 10 | 本应用使用了[图灵机器人](http://www.tuling123.com),需要申请到```atuling_key```,并配置到```robot.properties```中去。用户也可以自行更换为自己的机器人应用。如果不想使用图灵机器人,可以在配置里把参数```use_tuling```设置为false. 11 | 12 | #### 修改配置 13 | 本演示服务有2个配置文件在工程的```config```目录下,分别是```application.properties```和```robot.properties```。请正确配置放到jar包所在的目录下的```config```目录下。 14 | 15 | #### 运行 16 | 在```target```目录找到```robot-XXXX.jar```,把jar包和放置配置文件的```config```目录放到一起,然后执行下面命令: 17 | ``` 18 | java -jar robot-XXXXX.jar 19 | ``` 20 | 21 | #### 使用到的开源代码 22 | 1. [TypeBuilder](https://github.com/ikidou/TypeBuilder) 一个用于生成泛型的简易Builder 23 | 24 | #### LICENSE 25 | UNDER MIT LICENSE. 详情见LICENSE文件 26 | -------------------------------------------------------------------------------- /config/application.properties: -------------------------------------------------------------------------------- 1 | server.port=8883 -------------------------------------------------------------------------------- /config/robot.properties: -------------------------------------------------------------------------------- 1 | # 机器人ID 2 | robot.im_id=FireRobot 3 | # 机器人名称。在群里@机器人时,处理消息内容需要去掉机器人的名字。 4 | robot.im_name=小火 5 | # 注意端口是80端口,不是admin的18080端口 6 | robot.im_url=http://localhost 7 | # 注意secret是机器人的secret,不是admin的secret 8 | robot.im_secret=123456 9 | 10 | # 图灵机器人api 11 | robot.use_tuling=true 12 | robot.tuling_key=a09a38b7da2f4f058b3b07972b505ec4 13 | 14 | # 当前服务的公网地址,用来生成webhook地址。 15 | robot.public_addr=http://192.168.3.101:8883 16 | -------------------------------------------------------------------------------- /mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven2 Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 59 | if [ -z "$JAVA_HOME" ]; then 60 | if [ -x "/usr/libexec/java_home" ]; then 61 | export JAVA_HOME="`/usr/libexec/java_home`" 62 | else 63 | export JAVA_HOME="/Library/Java/Home" 64 | fi 65 | fi 66 | ;; 67 | esac 68 | 69 | if [ -z "$JAVA_HOME" ] ; then 70 | if [ -r /etc/gentoo-release ] ; then 71 | JAVA_HOME=`java-config --jre-home` 72 | fi 73 | fi 74 | 75 | if [ -z "$M2_HOME" ] ; then 76 | ## resolve links - $0 may be a link to maven's home 77 | PRG="$0" 78 | 79 | # need this for relative symlinks 80 | while [ -h "$PRG" ] ; do 81 | ls=`ls -ld "$PRG"` 82 | link=`expr "$ls" : '.*-> \(.*\)$'` 83 | if expr "$link" : '/.*' > /dev/null; then 84 | PRG="$link" 85 | else 86 | PRG="`dirname "$PRG"`/$link" 87 | fi 88 | done 89 | 90 | saveddir=`pwd` 91 | 92 | M2_HOME=`dirname "$PRG"`/.. 93 | 94 | # make it fully qualified 95 | M2_HOME=`cd "$M2_HOME" && pwd` 96 | 97 | cd "$saveddir" 98 | # echo Using m2 at $M2_HOME 99 | fi 100 | 101 | # For Cygwin, ensure paths are in UNIX format before anything is touched 102 | if $cygwin ; then 103 | [ -n "$M2_HOME" ] && 104 | M2_HOME=`cygpath --unix "$M2_HOME"` 105 | [ -n "$JAVA_HOME" ] && 106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 107 | [ -n "$CLASSPATH" ] && 108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 109 | fi 110 | 111 | # For Migwn, ensure paths are in UNIX format before anything is touched 112 | if $mingw ; then 113 | [ -n "$M2_HOME" ] && 114 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 115 | [ -n "$JAVA_HOME" ] && 116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 117 | # TODO classpath? 118 | fi 119 | 120 | if [ -z "$JAVA_HOME" ]; then 121 | javaExecutable="`which javac`" 122 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 123 | # readlink(1) is not available as standard on Solaris 10. 124 | readLink=`which readlink` 125 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 126 | if $darwin ; then 127 | javaHome="`dirname \"$javaExecutable\"`" 128 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 129 | else 130 | javaExecutable="`readlink -f \"$javaExecutable\"`" 131 | fi 132 | javaHome="`dirname \"$javaExecutable\"`" 133 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 134 | JAVA_HOME="$javaHome" 135 | export JAVA_HOME 136 | fi 137 | fi 138 | fi 139 | 140 | if [ -z "$JAVACMD" ] ; then 141 | if [ -n "$JAVA_HOME" ] ; then 142 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 143 | # IBM's JDK on AIX uses strange locations for the executables 144 | JAVACMD="$JAVA_HOME/jre/sh/java" 145 | else 146 | JAVACMD="$JAVA_HOME/bin/java" 147 | fi 148 | else 149 | JAVACMD="`which java`" 150 | fi 151 | fi 152 | 153 | if [ ! -x "$JAVACMD" ] ; then 154 | echo "Error: JAVA_HOME is not defined correctly." >&2 155 | echo " We cannot execute $JAVACMD" >&2 156 | exit 1 157 | fi 158 | 159 | if [ -z "$JAVA_HOME" ] ; then 160 | echo "Warning: JAVA_HOME environment variable is not set." 161 | fi 162 | 163 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 164 | 165 | # traverses directory structure from process work directory to filesystem root 166 | # first directory with .mvn subdirectory is considered project base directory 167 | find_maven_basedir() { 168 | 169 | if [ -z "$1" ] 170 | then 171 | echo "Path not specified to find_maven_basedir" 172 | return 1 173 | fi 174 | 175 | basedir="$1" 176 | wdir="$1" 177 | while [ "$wdir" != '/' ] ; do 178 | if [ -d "$wdir"/.mvn ] ; then 179 | basedir=$wdir 180 | break 181 | fi 182 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 183 | if [ -d "${wdir}" ]; then 184 | wdir=`cd "$wdir/.."; pwd` 185 | fi 186 | # end of workaround 187 | done 188 | echo "${basedir}" 189 | } 190 | 191 | # concatenates all lines of a file 192 | concat_lines() { 193 | if [ -f "$1" ]; then 194 | echo "$(tr -s '\n' ' ' < "$1")" 195 | fi 196 | } 197 | 198 | BASE_DIR=`find_maven_basedir "$(pwd)"` 199 | if [ -z "$BASE_DIR" ]; then 200 | exit 1; 201 | fi 202 | 203 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 204 | echo $MAVEN_PROJECTBASEDIR 205 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 206 | 207 | # For Cygwin, switch paths to Windows format before running java 208 | if $cygwin; then 209 | [ -n "$M2_HOME" ] && 210 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 211 | [ -n "$JAVA_HOME" ] && 212 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 213 | [ -n "$CLASSPATH" ] && 214 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 215 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 216 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 217 | fi 218 | 219 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 220 | 221 | exec "$JAVACMD" \ 222 | $MAVEN_OPTS \ 223 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 224 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 225 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 226 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 40 | 41 | @REM set %HOME% to equivalent of $HOME 42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 43 | 44 | @REM Execute a user defined script before this one 45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 49 | :skipRcPre 50 | 51 | @setlocal 52 | 53 | set ERROR_CODE=0 54 | 55 | @REM To isolate internal variables from possible post scripts, we use another setlocal 56 | @setlocal 57 | 58 | @REM ==== START VALIDATION ==== 59 | if not "%JAVA_HOME%" == "" goto OkJHome 60 | 61 | echo. 62 | echo Error: JAVA_HOME not found in your environment. >&2 63 | echo Please set the JAVA_HOME variable in your environment to match the >&2 64 | echo location of your Java installation. >&2 65 | echo. 66 | goto error 67 | 68 | :OkJHome 69 | if exist "%JAVA_HOME%\bin\java.exe" goto init 70 | 71 | echo. 72 | echo Error: JAVA_HOME is set to an invalid directory. >&2 73 | echo JAVA_HOME = "%JAVA_HOME%" >&2 74 | echo Please set the JAVA_HOME variable in your environment to match the >&2 75 | echo location of your Java installation. >&2 76 | echo. 77 | goto error 78 | 79 | @REM ==== END VALIDATION ==== 80 | 81 | :init 82 | 83 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 84 | @REM Fallback to current working directory if not found. 85 | 86 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 87 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 88 | 89 | set EXEC_DIR=%CD% 90 | set WDIR=%EXEC_DIR% 91 | :findBaseDir 92 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 93 | cd .. 94 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 95 | set WDIR=%CD% 96 | goto findBaseDir 97 | 98 | :baseDirFound 99 | set MAVEN_PROJECTBASEDIR=%WDIR% 100 | cd "%EXEC_DIR%" 101 | goto endDetectBaseDir 102 | 103 | :baseDirNotFound 104 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 105 | cd "%EXEC_DIR%" 106 | 107 | :endDetectBaseDir 108 | 109 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 110 | 111 | @setlocal EnableExtensions EnableDelayedExpansion 112 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 113 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 114 | 115 | :endReadAdditionalConfig 116 | 117 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 118 | 119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 121 | 122 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 123 | if ERRORLEVEL 1 goto error 124 | goto end 125 | 126 | :error 127 | set ERROR_CODE=1 128 | 129 | :end 130 | @endlocal & set ERROR_CODE=%ERROR_CODE% 131 | 132 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 133 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 134 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 135 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 136 | :skipRcPost 137 | 138 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 139 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 140 | 141 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 142 | 143 | exit /B %ERROR_CODE% 144 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | cn.wildfirechat 7 | robot 8 | 0.25 9 | jar 10 | 11 | robot 12 | Demo project for Spring Boot 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.2.10.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 1.8 25 | 1.2.1 26 | 4.1.12.Final 27 | 2.17.1 28 | 29 | 30 | 31 | 32 | org.springframework.boot 33 | spring-boot-starter 34 | 35 | 36 | 37 | org.springframework.boot 38 | spring-boot-starter-web 39 | 40 | 41 | 42 | org.springframework.boot 43 | spring-boot-starter-test 44 | test 45 | 46 | 47 | 48 | org.slf4j 49 | slf4j-api 50 | 1.7.5 51 | 52 | 53 | 54 | org.slf4j 55 | slf4j-log4j12 56 | 1.7.5 57 | 58 | 59 | 60 | org.apache.logging.log4j 61 | log4j-slf4j-impl 62 | ${log4j2.version} 63 | 64 | 65 | org.apache.logging.log4j 66 | log4j-api 67 | ${log4j2.version} 68 | 69 | 70 | org.apache.logging.log4j 71 | log4j-core 72 | ${log4j2.version} 73 | 74 | 75 | org.apache.logging.log4j 76 | log4j-to-slf4j 77 | ${log4j2.version} 78 | 79 | 80 | 81 | com.google.code.gson 82 | gson 83 | 2.8.9 84 | 85 | 86 | 87 | commons-httpclient 88 | commons-httpclient 89 | 3.1 90 | 91 | 92 | 93 | org.apache.httpcomponents 94 | httpclient 95 | 4.5.13 96 | 97 | 98 | 99 | commons-codec 100 | commons-codec 101 | 1.11 102 | compile 103 | 104 | 105 | 106 | com.google.protobuf 107 | protobuf-java 108 | 2.5.0 109 | 110 | 111 | 112 | com.googlecode.json-simple 113 | json-simple 114 | 1.1.1 115 | 116 | 117 | 118 | cn.wildfirechat 119 | sdk 120 | ${wfc.sdk.version} 121 | system 122 | ${project.basedir}/src/lib/sdk-${wfc.sdk.version}.jar 123 | 124 | 125 | 126 | cn.wildfirechat 127 | common 128 | ${wfc.sdk.version} 129 | system 130 | ${project.basedir}/src/lib/common-${wfc.sdk.version}.jar 131 | 132 | 133 | 134 | io.netty 135 | netty-common 136 | ${netty.version} 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | org.springframework.boot 145 | spring-boot-maven-plugin 146 | 147 | true 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | -------------------------------------------------------------------------------- /src/lib/common-1.2.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/robot_server/c5c5d2b8137be2d47b6d5229a608a93d68f7a102/src/lib/common-1.2.1.jar -------------------------------------------------------------------------------- /src/lib/sdk-1.2.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/robot_server/c5c5d2b8137be2d47b6d5229a608a93d68f7a102/src/lib/sdk-1.2.1.jar -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/Application.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class Application { 8 | public static void main(String[] args) { 9 | SpringApplication.run(Application.class, args); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/Controller.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app; 2 | 3 | import cn.wildfirechat.app.webhook.WebhookService; 4 | import cn.wildfirechat.pojos.OutputMessageData; 5 | import cn.wildfirechat.pojos.SendMessageData; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.web.bind.annotation.*; 8 | 9 | import javax.servlet.http.HttpServletRequest; 10 | 11 | @RestController 12 | public class Controller { 13 | @Autowired 14 | private Service mService; 15 | 16 | @Autowired 17 | private WebhookService webhookService; 18 | 19 | @PostMapping(value = "/robot/recvmsg", produces = "application/json;charset=UTF-8" ) 20 | public Object recvMsg(@RequestBody OutputMessageData messageData) { 21 | mService.onReceiveMessage(messageData); 22 | return "ok"; 23 | } 24 | 25 | 26 | @PostMapping(value = "/robot/webhook/{app}/{token}", produces = "application/json;charset=UTF-8" ) 27 | public Object webhook(HttpServletRequest request, @PathVariable("app") String app, @PathVariable("token") String token, @RequestBody String payload) { 28 | return webhookService.handleWebhookPost(request, "/"+app, token, payload); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/DESUtil.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app; 2 | 3 | import javax.crypto.Cipher; 4 | import javax.crypto.CipherInputStream; 5 | import javax.crypto.CipherOutputStream; 6 | import javax.crypto.SecretKeyFactory; 7 | import javax.crypto.spec.DESKeySpec; 8 | import javax.crypto.spec.IvParameterSpec; 9 | import java.io.*; 10 | import java.security.Key; 11 | import java.util.Base64; 12 | 13 | public class DESUtil { 14 | 15 | 16 | /** 17 | * 偏移变量,固定占8位字节 18 | */ 19 | private final static String IV_PARAMETER = "12345678"; 20 | /** 21 | * 密钥算法 22 | */ 23 | private static final String ALGORITHM = "DES"; 24 | /** 25 | * 加密/解密算法-工作模式-填充模式 26 | */ 27 | private static final String CIPHER_ALGORITHM = "DES/CBC/PKCS5Padding"; 28 | /** 29 | * 默认编码 30 | */ 31 | private static final String CHARSET = "utf-8"; 32 | 33 | private static final String password = "ax8123csdd"; 34 | 35 | /** 36 | * 生成key 37 | * 38 | * @param password 39 | * @return 40 | * @throws Exception 41 | */ 42 | private static Key generateKey(String password) throws Exception { 43 | DESKeySpec dks = new DESKeySpec(password.getBytes(CHARSET)); 44 | SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM); 45 | return keyFactory.generateSecret(dks); 46 | } 47 | 48 | 49 | /** 50 | * DES加密字符串 51 | * 52 | * @param data 待加密字符串 53 | * @return 加密后内容 54 | */ 55 | public static String encrypt(String data) { 56 | if (password== null || password.length() < 8) { 57 | throw new RuntimeException("加密失败,key不能小于8位"); 58 | } 59 | if (data == null) 60 | return null; 61 | try { 62 | Key secretKey = generateKey(password); 63 | Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM); 64 | IvParameterSpec iv = new IvParameterSpec(IV_PARAMETER.getBytes(CHARSET)); 65 | cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv); 66 | byte[] bytes = cipher.doFinal(data.getBytes(CHARSET)); 67 | 68 | //JDK1.8及以上可直接使用Base64,JDK1.7及以下可以使用BASE64Encoder 69 | //Android平台可以使用android.util.Base64 70 | String s = new String(Base64.getEncoder().encode(bytes)); 71 | s = s.replace("/", "~").replace("+","-").replace("=","_"); 72 | return s; 73 | } catch (Exception e) { 74 | e.printStackTrace(); 75 | return data; 76 | } 77 | } 78 | 79 | /** 80 | * DES解密字符串 81 | * 82 | * @param data 待解密字符串 83 | * @return 解密后内容 84 | */ 85 | public static String decrypt(String data) { 86 | if (data == null) 87 | return null; 88 | try { 89 | data = data.replace("~", "/").replace("-", "+").replace("_", "="); 90 | Key secretKey = generateKey(password); 91 | Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM); 92 | IvParameterSpec iv = new IvParameterSpec(IV_PARAMETER.getBytes(CHARSET)); 93 | cipher.init(Cipher.DECRYPT_MODE, secretKey, iv); 94 | return new String(cipher.doFinal(Base64.getDecoder().decode(data.getBytes(CHARSET))), CHARSET); 95 | } catch (Exception e) { 96 | e.printStackTrace(); 97 | return data; 98 | } 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/ExecutorConfig.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.scheduling.annotation.EnableAsync; 6 | import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; 7 | 8 | import java.util.concurrent.Executor; 9 | 10 | @Configuration 11 | @EnableAsync 12 | public class ExecutorConfig { 13 | 14 | @Bean 15 | public Executor asyncExecutor() { 16 | ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); 17 | executor.setCorePoolSize(10); 18 | executor.setMaxPoolSize(10); 19 | executor.initialize(); 20 | return executor; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/HttpUtils.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app; 2 | 3 | import cn.wildfirechat.sdk.model.IMResult; 4 | import com.google.gson.Gson; 5 | import ikidou.reflect.TypeBuilder; 6 | import org.apache.commons.codec.digest.DigestUtils; 7 | import org.apache.http.HttpResponse; 8 | import org.apache.http.HttpStatus; 9 | import org.apache.http.client.HttpClient; 10 | import org.apache.http.client.methods.HttpPost; 11 | import org.apache.http.entity.StringEntity; 12 | import org.apache.http.impl.client.HttpClientBuilder; 13 | import org.slf4j.Logger; 14 | import org.slf4j.LoggerFactory; 15 | 16 | import java.io.BufferedReader; 17 | import java.io.InputStreamReader; 18 | import java.lang.reflect.Type; 19 | import java.nio.charset.Charset; 20 | 21 | 22 | public class HttpUtils { 23 | private static final Logger LOG = LoggerFactory.getLogger(HttpUtils.class); 24 | 25 | static public T post(String url, Object object, Class clazz) throws Exception{ 26 | 27 | HttpPost post = null; 28 | try { 29 | HttpClient httpClient = HttpClientBuilder.create().build(); 30 | 31 | post = new HttpPost(url); 32 | post.setHeader("Content-type", "application/json; charset=utf-8"); 33 | post.setHeader("Connection", "Keep-Alive"); 34 | 35 | String jsonStr; 36 | if (object instanceof String) { 37 | jsonStr = (String) object; 38 | } else { 39 | jsonStr = new Gson().toJson(object); 40 | } 41 | 42 | LOG.info("http request content: {}", jsonStr); 43 | 44 | StringEntity entity = new StringEntity(jsonStr, Charset.forName("UTF-8")); 45 | entity.setContentEncoding("UTF-8"); 46 | entity.setContentType("application/json"); 47 | post.setEntity(entity); 48 | HttpResponse response = httpClient.execute(post); 49 | 50 | int statusCode = response.getStatusLine().getStatusCode(); 51 | if(statusCode != HttpStatus.SC_OK){ 52 | LOG.info("Request error: "+statusCode); 53 | throw new Exception("Http request error with code:" + statusCode); 54 | }else{ 55 | BufferedReader in = new BufferedReader(new InputStreamReader(response.getEntity() 56 | .getContent(),"utf-8")); 57 | StringBuffer sb = new StringBuffer(); 58 | String line; 59 | String NL = System.getProperty("line.separator"); 60 | while ((line = in.readLine()) != null) { 61 | sb.append(line + NL); 62 | } 63 | 64 | in.close(); 65 | 66 | String content = sb.toString(); 67 | LOG.info("http request response content: {}", content); 68 | 69 | return new Gson().fromJson(content, clazz); 70 | } 71 | } catch (Exception e) { 72 | e.printStackTrace(); 73 | throw e; 74 | }finally{ 75 | if(post != null){ 76 | post.releaseConnection(); 77 | } 78 | } 79 | } 80 | 81 | private static IMResult fromJsonObject(String content, Class clazz) { 82 | Type type = TypeBuilder 83 | .newInstance(IMResult.class) 84 | .addTypeParam(clazz) 85 | .build(); 86 | return new Gson().fromJson(content, type); 87 | } 88 | 89 | private static boolean isNullOrEmpty(String str) { 90 | return str == null || str.isEmpty(); 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/RobotConfig.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.context.annotation.PropertySource; 6 | 7 | @Configuration 8 | @ConfigurationProperties(prefix="robot") 9 | @PropertySource(value = "file:config/robot.properties", encoding = "UTF-8") 10 | public class RobotConfig { 11 | public String im_url; 12 | public String im_secret; 13 | public String im_id; 14 | public String im_name; 15 | 16 | public boolean use_tuling; 17 | 18 | public String tuling_key; 19 | 20 | public String public_addr; 21 | 22 | public boolean isUse_tuling() { 23 | return use_tuling; 24 | } 25 | 26 | public void setUse_tuling(boolean use_tuling) { 27 | this.use_tuling = use_tuling; 28 | } 29 | 30 | public String getTuling_key() { 31 | return tuling_key; 32 | } 33 | 34 | public void setTuling_key(String tuling_key) { 35 | this.tuling_key = tuling_key; 36 | } 37 | 38 | public String getIm_name() { 39 | return im_name; 40 | } 41 | 42 | public void setIm_name(String im_name) { 43 | this.im_name = im_name; 44 | } 45 | 46 | public String getIm_id() { 47 | return im_id; 48 | } 49 | 50 | public void setIm_id(String im_id) { 51 | this.im_id = im_id; 52 | } 53 | 54 | public String getIm_url() { 55 | return im_url; 56 | } 57 | 58 | public void setIm_url(String im_url) { 59 | this.im_url = im_url; 60 | } 61 | 62 | public String getIm_secret() { 63 | return im_secret; 64 | } 65 | 66 | public void setIm_secret(String im_secret) { 67 | this.im_secret = im_secret; 68 | } 69 | 70 | public String getPublic_addr() { 71 | return public_addr; 72 | } 73 | 74 | public void setPublic_addr(String public_addr) { 75 | this.public_addr = public_addr; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/Service.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app; 2 | 3 | 4 | import cn.wildfirechat.pojos.OutputMessageData; 5 | import cn.wildfirechat.pojos.SendMessageData; 6 | 7 | public interface Service { 8 | void onReceiveMessage(OutputMessageData messageData); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/ServiceImpl.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app; 2 | 3 | import cn.wildfirechat.app.tuling.TulingService; 4 | import cn.wildfirechat.app.webhook.WebhookService; 5 | import cn.wildfirechat.common.ErrorCode; 6 | import cn.wildfirechat.messagecontentbuilder.StreamingTextMessageContentBuilder; 7 | import cn.wildfirechat.pojos.*; 8 | import cn.wildfirechat.proto.ProtoConstants; 9 | import cn.wildfirechat.sdk.MessageAdmin; 10 | import cn.wildfirechat.sdk.RobotService; 11 | import cn.wildfirechat.sdk.model.*; 12 | import org.slf4j.Logger; 13 | import org.slf4j.LoggerFactory; 14 | import org.springframework.beans.factory.annotation.Autowired; 15 | import org.springframework.scheduling.annotation.Async; 16 | import sun.misc.BASE64Encoder; 17 | 18 | import javax.annotation.PostConstruct; 19 | import java.util.Arrays; 20 | import java.util.UUID; 21 | 22 | @org.springframework.stereotype.Service 23 | public class ServiceImpl implements Service { 24 | private static final Logger LOG = LoggerFactory.getLogger(ServiceImpl.class); 25 | 26 | @Autowired 27 | private RobotConfig mRobotConfig; 28 | 29 | @Autowired 30 | private WebhookService webhookService; 31 | 32 | @Autowired 33 | private TulingService tulingService; 34 | 35 | private RobotService robotService; 36 | 37 | @PostConstruct 38 | private void init() { 39 | robotService = new RobotService(mRobotConfig.im_url, mRobotConfig.getIm_id(), mRobotConfig.im_secret); 40 | } 41 | 42 | // int ConversationType_Private = 0; 43 | // int ConversationType_Group = 1; 44 | // int ConversationType_ChatRoom = 2; 45 | // int ConversationType_Channel = 3; 46 | // int ConversationType_Thing = 4; 47 | @Override 48 | @Async("asyncExecutor") 49 | public void onReceiveMessage(OutputMessageData messageData) { 50 | LOG.info("on receive message {}", messageData.getMessageId()); 51 | boolean needResponse = false; 52 | if (messageData.getConv().getType() == 0) { 53 | needResponse = true; 54 | } 55 | if (!needResponse && messageData.getConv().getType() == 1) { 56 | if (messageData.getPayload() != null) { 57 | if (messageData.getPayload().getMentionedType() == 2) { 58 | //needResponse = true; 59 | needResponse = false; //@全体时,机器人就别乱回复捣乱了 60 | } else if (messageData.getPayload().getMentionedType() == 1) { 61 | if (messageData.getPayload().getMentionedTarget() != null && messageData.getPayload().getMentionedTarget().contains(mRobotConfig.getIm_id())) { 62 | needResponse = true; 63 | } 64 | } 65 | } 66 | } 67 | // public interface ContentType { 68 | // int Unknown = 0; 69 | // int Text = 1; 70 | // int Image = 2; 71 | // int Voice = 3; 72 | // int Location = 4; 73 | // int Video = 5; 74 | // int RichMedia = 6; 75 | // } 76 | if (needResponse) { 77 | Conversation conversation = messageData.getConv(); 78 | if (conversation.getType() == 0) { 79 | conversation.setTarget(messageData.getSender()); 80 | } 81 | 82 | String response = messageData.getPayload().getSearchableContent(); 83 | boolean localResponse = true; 84 | 85 | LOG.info("msg:{}, robotName:{}", response, mRobotConfig.im_name); 86 | response = response.replace("@" + mRobotConfig.im_name, "").trim(); 87 | LOG.info("msg:{}, robotName:{}", response, mRobotConfig.im_name); 88 | if (messageData.getPayload().getType() == 1) { 89 | if(response.contains("地址") || response.contains("文档") || response.contains("论坛") || response.contains("官网")) { 90 | localResponse = false; 91 | response = "项目地址在: https://github.com/wildfirechat。 文档地址在: https://docs.wildfirechat.cn。论坛地址在: https://bbs.wildfirechat.cn。官网地址在:https://wildfirechat.cn"; 92 | } else if(response.startsWith("公众号")) { 93 | localResponse = false; 94 | response = "请关注微信公众号:野火IM"; 95 | } else if(response.startsWith("价格") || response.startsWith("收费") || response.startsWith("费用")) { 96 | localResponse = false; 97 | response = "野火IM相关价格,请参考我们的文档: http://docs.wildfirechat.cn"; 98 | } else if(response.startsWith("商务") || response.startsWith("购买") || response.startsWith("联系")) { 99 | localResponse = false; 100 | response = "请微信联系 wildfirechat 或 wfchat 进行商务交流"; 101 | } else if(response.startsWith("问题") || response.startsWith("崩溃")) { 102 | localResponse = false; 103 | response = "请确保是按照文档进行对接使用。请检索github issue或者论坛bbs.wildfirechat.cn。如果还无法解决请提issue或者论坛发帖"; 104 | } else if(response.equalsIgnoreCase("/list") || response.equalsIgnoreCase("/")) { 105 | if (conversation.getType() == 1 || conversation.getType() == 0) { 106 | response = webhookService.InvokeCommands(); 107 | } else { 108 | response = "仅支持群组和私聊"; 109 | } 110 | } else if(response.equals("流式文本")) { 111 | testStreamingText(conversation); 112 | return; 113 | } else if(webhookService.handleInvokeCommand(response, messageData.getSender(), messageData.getConv())) { 114 | return; 115 | } else { 116 | response = tulingService.handleWord(messageData.getSender(), response); 117 | } 118 | } else if (messageData.getPayload().getType() == 3) { 119 | localResponse = false; 120 | response = "不好意思,我还不会看照片哟~"; 121 | } else if (messageData.getPayload().getType() == 2) { 122 | localResponse = false; 123 | response = "不好意思,我还不会听声音哟~"; 124 | } else if (messageData.getPayload().getType() == 4) { 125 | localResponse = false; 126 | response = "这是那里?我还没有学会看地图啊!"; 127 | } else if (messageData.getPayload().getType() == 6) { 128 | localResponse = false; 129 | response = "我也想看视频,可惜我还没学会!"; 130 | } else if (messageData.getPayload().getType() == 400) { 131 | localResponse = false; 132 | response = "别给我打电话了,我是个机器人,还不会接电话,还没有人教过我啊!"; 133 | 134 | MessagePayload payload = new MessagePayload(); 135 | payload.setType(402); 136 | payload.setContent(messageData.getPayload().getContent()); 137 | String reason = "{\"r\":5}"; 138 | payload.setBase64edData(new BASE64Encoder().encode(reason.getBytes())); 139 | try { 140 | robotService.sendMessage(mRobotConfig.getIm_id(), conversation, payload); 141 | } catch (Exception e) { 142 | e.printStackTrace(); 143 | } 144 | } else if(messageData.getPayload().getType() > 400 && messageData.getPayload().getType() < 500) { 145 | //voip signal message, ignore it 146 | return; 147 | } 148 | 149 | if(localResponse) { 150 | if (messageData.getPayload().getType() != 1) { 151 | response = "我不明白你在说什么"; 152 | } else { 153 | response = response.replace("@" + mRobotConfig.getIm_name() + " ", ""); 154 | response = response.replace("@" + mRobotConfig.getIm_name(), ""); 155 | response = response.replace("我", ""); 156 | response = response.replace("吗", ""); 157 | response = response.replace("你是谁", "我是" + mRobotConfig.getIm_name() + "呀"); 158 | response = response.replace("你", "我"); 159 | response = response.replace("?", "!"); 160 | response = response.replace("? ", "!"); 161 | response = response.replace("?", "!"); 162 | response = response.replace("? ", "!"); 163 | if (response.equals(messageData.getPayload().getSearchableContent())) { 164 | response = "我不明白你在说什么"; 165 | } 166 | } 167 | } 168 | 169 | MessagePayload payload = new MessagePayload(); 170 | payload.setType(1); 171 | payload.setSearchableContent(response); 172 | if (conversation.getType() == 1 && messageData.getPayload().getType() == 1) { //群里的文本,加上@信息 173 | InputOutputUserInfo sender = null; 174 | try { 175 | IMResult result = robotService.getUserInfo(messageData.getSender()); 176 | if (result.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) { 177 | sender = result.getResult(); 178 | } 179 | } catch (Exception e) { 180 | e.printStackTrace(); 181 | } 182 | if (sender != null && sender.getDisplayName() != null) { 183 | payload.setSearchableContent("@" + sender.getDisplayName() + " " + payload.getSearchableContent()); 184 | payload.setMentionedType(1); 185 | payload.setMentionedTarget(Arrays.asList(messageData.getSender())); 186 | } 187 | } 188 | try { 189 | IMResult result = robotService.sendMessage(mRobotConfig.getIm_id(), conversation, payload); 190 | if (result != null) { 191 | if (result.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) { 192 | LOG.info("Send response success"); 193 | } else { 194 | LOG.error("Send response error {}", result.getCode()); 195 | } 196 | } else { 197 | LOG.error("Send response is null"); 198 | } 199 | } catch (Exception e) { 200 | e.printStackTrace(); 201 | LOG.error("Send response execption"); 202 | } 203 | } 204 | return; 205 | } 206 | 207 | 208 | void testStreamingText(Conversation conversation) { 209 | String fullText = "北京野火无限网络科技有限公司是成立于2019年底的一家科技创新企业,公司的主要目标是为广大企业和单位提供优质可控、私有部署的即时通讯和实时音视频能力,为社会信息化水平提高作出自己的贡献。\n" + 210 | "\n" + 211 | "野火IM是公司研发一套自主可控的即时通讯组件,具有全部私有化、功能齐全、协议稳定可靠、全平台支持、安全性高和支持国产化等技术特点。客户端分层设计,既可开箱即用,也可与现有系统深度融合。具有完善的服务端API和自定义消息功能,可以任意扩展功能。代码开源率高,方便二次开发和使用。支持多人实时音视频和会议功能,线上沟通更通畅。\n" + 212 | "\n" + 213 | "公司致力于开源项目,在Github上开源项目广受好评,其中Server项目有超过7.1K个Star,组织合计Star超过1万个。有大量的技术公司受益于我们的开源,为自己的产品添加了即时通讯能力,这也算是我们公司为社会信息化建设做出的一点点贡献吧。\n" + 214 | "\n" + 215 | "公司以即时通讯技术为核心,持续努力优化和完善即时通讯和实时音视频产品,努力为客户提供最优质的即时通讯和实时音视频能力。"; 216 | int i = 0; 217 | String streamId = UUID.randomUUID().toString(); 218 | while (i < fullText.length()) { 219 | i+= 15; 220 | 221 | boolean finish = i >= fullText.length(); 222 | String partText = finish?fullText:fullText.substring(0, i); 223 | 224 | MessagePayload payload = StreamingTextMessageContentBuilder.newBuilder(streamId).text(partText).generating(!finish).build(); 225 | 226 | try { 227 | IMResult resultSendMessage = robotService.sendMessage(mRobotConfig.getIm_id(), conversation, payload); 228 | if (resultSendMessage != null && resultSendMessage.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) { 229 | System.out.println("send message success"); 230 | } else { 231 | System.out.println("send message failure"); 232 | return; 233 | } 234 | 235 | Thread.sleep(500); 236 | } catch (Exception e) { 237 | e.printStackTrace(); 238 | return; 239 | } 240 | } 241 | } 242 | } 243 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/TokenUtils.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app; 2 | 3 | import cn.wildfirechat.pojos.Conversation; 4 | 5 | public class TokenUtils { 6 | private static final String signWord = "hello world"; 7 | public static String webhookToken(Conversation conversation, String user) { 8 | String key = conversation.getType() + "|" + conversation.getLine() + "|" + conversation.getTarget() + signWord + user; 9 | return DESUtil.encrypt(key); 10 | } 11 | 12 | public static String userFromToken(String token) { 13 | String s = DESUtil.decrypt(token); 14 | if(s == null) { 15 | return null; 16 | } 17 | 18 | return s.substring(s.indexOf(signWord) + signWord.length()); 19 | } 20 | public static Conversation conversationFromToken(String token) { 21 | String s = DESUtil.decrypt(token); 22 | if(s == null) { 23 | return null; 24 | } 25 | Conversation conversation = new Conversation(); 26 | String[] arr = s.split("\\|"); 27 | conversation.setType(Integer.parseInt(arr[0])); 28 | conversation.setLine(Integer.parseInt(arr[1])); 29 | String target = s.substring((conversation.getType()+"|"+conversation.getLine()+"|").length(), s.indexOf(signWord)); 30 | conversation.setTarget(target); 31 | return conversation; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/tuling/TulingResponse.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.tuling; 2 | 3 | import java.util.List; 4 | 5 | public class TulingResponse { 6 | public static class Intent { 7 | int code; 8 | String intentName; 9 | String actionName; 10 | } 11 | public static class Value { 12 | String url; 13 | String text; 14 | } 15 | public static class Result { 16 | int groupType; 17 | String resultType; 18 | Value values; 19 | } 20 | public Intent intent; 21 | public List results; 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/tuling/TulingService.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.tuling; 2 | 3 | import cn.wildfirechat.app.HttpUtils; 4 | import cn.wildfirechat.app.RobotConfig; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Service; 7 | import org.springframework.util.StringUtils; 8 | 9 | @Service 10 | public class TulingService { 11 | @Autowired 12 | private RobotConfig mRobotConfig; 13 | 14 | public String handleWord(String sender, String text) { 15 | String response = ""; 16 | if (mRobotConfig.use_tuling) { 17 | String searchReq = "{\n" + "\t\"reqType\":0,\n" + " \"perception\": {\n" + " \"inputText\": {\n" + " \"text\": \"${TEXT}\"\n" + " }\n" + " },\n" + " \"userInfo\": {\n" + " \"apiKey\": \"${APIKEY}\",\n" + " \"userId\": \"${USERID}\"\n" + " }\n" + "}"; 18 | searchReq = searchReq.replace("${APIKEY}", mRobotConfig.getTuling_key()).replace("${USERID}", Math.abs(sender.hashCode()) + ""); 19 | searchReq = searchReq.replace("${TEXT}", text); 20 | 21 | 22 | try { 23 | TulingResponse s = HttpUtils.post("http://openapi.tuling123.com/openapi/api/v2", searchReq, TulingResponse.class); 24 | if (s != null) { 25 | if (s.results != null && s.results.size() > 0) { 26 | for (TulingResponse.Result result : s.results 27 | ) { 28 | if (result.values != null) { 29 | if (!StringUtils.isEmpty(result.values.text)) { 30 | if(StringUtils.isEmpty(response)) { 31 | response = result.values.text; 32 | } else { 33 | response = response + " \n" + result.values.text; 34 | } 35 | } 36 | 37 | if (!StringUtils.isEmpty(result.values.url)) { 38 | if(StringUtils.isEmpty(response)) { 39 | response = result.values.url; 40 | } else { 41 | response = response + " \n" + result.values.url; 42 | } 43 | } 44 | } 45 | } 46 | } 47 | } 48 | } catch (Exception e) { 49 | e.printStackTrace(); 50 | } 51 | } 52 | return response; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/IWebhook.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook; 2 | 3 | import cn.wildfirechat.pojos.MessagePayload; 4 | 5 | import javax.servlet.http.HttpServletRequest; 6 | 7 | public interface IWebhook { 8 | interface SendMessageCallback { 9 | void sendMessage(MessagePayload payload); 10 | } 11 | 12 | String invokeCommand(); 13 | Object handleWebhookPost(HttpServletRequest request, String user, String body, SendMessageCallback callback); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/WebhookService.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook; 2 | 3 | import cn.wildfirechat.app.RobotConfig; 4 | import cn.wildfirechat.app.TokenUtils; 5 | import cn.wildfirechat.app.webhook.general.GeneralWebhook; 6 | import cn.wildfirechat.app.webhook.gitee.GiteeWebhook; 7 | import cn.wildfirechat.app.webhook.github.GithubWebhook; 8 | import cn.wildfirechat.app.webhook.gitlab.GitLabWebhook; 9 | import cn.wildfirechat.common.ErrorCode; 10 | import cn.wildfirechat.pojos.Conversation; 11 | import cn.wildfirechat.pojos.InputOutputUserInfo; 12 | import cn.wildfirechat.pojos.MessagePayload; 13 | import cn.wildfirechat.pojos.SendMessageResult; 14 | import cn.wildfirechat.sdk.RobotService; 15 | import cn.wildfirechat.sdk.model.IMResult; 16 | import org.slf4j.Logger; 17 | import org.slf4j.LoggerFactory; 18 | import org.springframework.beans.factory.annotation.Autowired; 19 | import org.springframework.stereotype.Service; 20 | 21 | import javax.annotation.PostConstruct; 22 | import javax.servlet.http.HttpServletRequest; 23 | import javax.validation.Payload; 24 | import java.util.HashMap; 25 | import java.util.Map; 26 | import java.util.concurrent.ConcurrentHashMap; 27 | 28 | @Service 29 | public class WebhookService { 30 | private static class Pair { 31 | public String key; 32 | public long value; 33 | 34 | public Pair(String key, long value) { 35 | this.key = key; 36 | this.value = value; 37 | } 38 | 39 | public String getKey() { 40 | return key; 41 | } 42 | 43 | public long getValue() { 44 | return value; 45 | } 46 | } 47 | private static final Logger LOG = LoggerFactory.getLogger(WebhookService.class); 48 | @Autowired 49 | private RobotConfig mRobotConfig; 50 | 51 | private Map webhookMap; 52 | 53 | private Map userNameCache = new ConcurrentHashMap<>(); 54 | 55 | 56 | private RobotService robotService; 57 | 58 | @PostConstruct 59 | void init() { 60 | webhookMap = new HashMap<>(); 61 | 62 | IWebhook github = new GithubWebhook(); 63 | IWebhook gitlab = new GitLabWebhook(); 64 | IWebhook general = new GeneralWebhook(); 65 | IWebhook gitee = new GiteeWebhook(); 66 | 67 | webhookMap.put(general.invokeCommand(), general); 68 | webhookMap.put(github.invokeCommand(), github); 69 | webhookMap.put(gitlab.invokeCommand(), gitlab); 70 | webhookMap.put(gitee.invokeCommand(), gitee); 71 | 72 | robotService = new RobotService(mRobotConfig.im_url, mRobotConfig.getIm_id(), mRobotConfig.im_secret); 73 | } 74 | 75 | public String InvokeCommands() { 76 | String commands = ""; 77 | for (String command : webhookMap.keySet()) { 78 | commands += command; 79 | commands += "\n"; 80 | } 81 | 82 | return commands; 83 | } 84 | 85 | public boolean handleInvokeCommand(String command, String fromUser, Conversation conversation) { 86 | if(webhookMap.containsKey(command)) { 87 | IWebhook webhook = webhookMap.get(command); 88 | String callback = mRobotConfig.getPublic_addr() 89 | + "/robot" 90 | + "/webhook" 91 | + webhook.invokeCommand() 92 | + "/" + TokenUtils.webhookToken(conversation, fromUser); 93 | 94 | String response = "您请求应用的webhook地址为:\n" + callback; 95 | if(conversation.getType() == 0) { 96 | sendMessage(conversation, response); 97 | } else if(conversation.getType() == 1) { 98 | Conversation privateConv = new Conversation(); 99 | privateConv.setLine(conversation.getLine()); 100 | privateConv.setType(0); 101 | privateConv.setTarget(fromUser); 102 | sendMessage(privateConv, response); 103 | sendMessage(conversation, "Webhook地址已经发送给您本人了,请到您与机器人的单聊会话查收"); 104 | } 105 | return true; 106 | } 107 | return false; 108 | } 109 | 110 | public Object handleWebhookPost(HttpServletRequest request, String app, String token, String body) { 111 | LOG.info("receive callback {}", app); 112 | if(webhookMap.containsKey(app)) { 113 | IWebhook webhook = webhookMap.get(app); 114 | String user = TokenUtils.userFromToken(token); 115 | Conversation conversation = TokenUtils.conversationFromToken(token); 116 | LOG.info("user {}", user); 117 | if(user != null) { 118 | Pair namePair = userNameCache.computeIfAbsent(user, s -> { 119 | try { 120 | IMResult inputOutputUserInfo = robotService.getUserInfo(s); 121 | if(inputOutputUserInfo != null && inputOutputUserInfo.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS && inputOutputUserInfo.getResult() != null) { 122 | return new Pair(inputOutputUserInfo.getResult().getDisplayName(), System.currentTimeMillis()); 123 | } 124 | } catch (Exception e) { 125 | e.printStackTrace(); 126 | } 127 | return new Pair("user " + s, System.currentTimeMillis()); 128 | }); 129 | if(namePair.getValue() + 24 * 60 * 60 * 1000 < System.currentTimeMillis()) { 130 | userNameCache.remove(user); 131 | } 132 | 133 | return webhook.handleWebhookPost(request, namePair.getKey(), body, payload -> { 134 | sendMessage(conversation, payload); 135 | }); 136 | } 137 | } 138 | return "ok"; 139 | } 140 | 141 | private void sendMessage(Conversation conversation, MessagePayload payload) { 142 | IMResult result = null; 143 | try { 144 | result = robotService.sendMessage(mRobotConfig.getIm_id(), conversation, payload); 145 | } catch (Exception e) { 146 | e.printStackTrace(); 147 | } 148 | 149 | if (result != null) { 150 | if (result.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) { 151 | LOG.info("Send response success"); 152 | } else { 153 | LOG.error("Send response error {}", result.getCode()); 154 | } 155 | } else { 156 | LOG.error("Send response error"); 157 | } 158 | } 159 | 160 | private void sendMessage(Conversation conversation, String text) { 161 | MessagePayload payload = new MessagePayload(); 162 | payload.setType(1); 163 | payload.setSearchableContent(text); 164 | sendMessage(conversation, payload); 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/general/GeneralWebhook.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.general; 2 | 3 | import cn.wildfirechat.app.webhook.IWebhook; 4 | import cn.wildfirechat.pojos.MessagePayload; 5 | import org.apache.commons.codec.binary.Base64; 6 | import org.json.simple.JSONObject; 7 | import org.json.simple.parser.JSONParser; 8 | import org.json.simple.parser.ParseException; 9 | 10 | import javax.servlet.http.HttpServletRequest; 11 | import java.nio.charset.StandardCharsets; 12 | 13 | public class GeneralWebhook implements IWebhook { 14 | @Override 15 | public String invokeCommand() { 16 | return "/general"; 17 | } 18 | 19 | @Override 20 | public Object handleWebhookPost(HttpServletRequest request, String user, String body, SendMessageCallback callback) { 21 | MessagePayload messagePayload = new MessagePayload(); 22 | try { 23 | JSONObject object = (JSONObject)(new JSONParser().parse(body)); 24 | long type = (Long) object.get("type"); 25 | if(type == 1) { 26 | String text = (String)object.get("text"); 27 | messagePayload.setType(1); 28 | messagePayload.setSearchableContent(text + "\n\n来自 " + user + " 的机器人消息"); 29 | } else if(type == 8) { 30 | String title = (String) object.get("title"); 31 | String digest = (String) object.get("digest"); 32 | String url = (String) object.get("url"); 33 | messagePayload.setType(8); 34 | messagePayload.setSearchableContent(title); 35 | JSONObject jsonObject = new JSONObject(); 36 | jsonObject.put("d", digest); 37 | jsonObject.put("u", url); 38 | messagePayload.setBase64edData(new Base64().encodeAsString(jsonObject.toString().getBytes(StandardCharsets.UTF_8))); 39 | } else { 40 | messagePayload.setType(1); 41 | messagePayload.setSearchableContent(body + "\n\n来自 " + user + " 的机器人消息"); 42 | } 43 | } catch (Exception e) { 44 | e.printStackTrace(); 45 | messagePayload.setType(1); 46 | messagePayload.setSearchableContent(body + "\n\n来自 " + user + " 的机器人消息"); 47 | } 48 | 49 | callback.sendMessage(messagePayload); 50 | return "ok"; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/gitee/GiteeWebhook.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.gitee; 2 | 3 | import cn.wildfirechat.app.webhook.IWebhook; 4 | import cn.wildfirechat.app.webhook.gitee.pojo.*; 5 | import cn.wildfirechat.pojos.MessagePayload; 6 | import com.google.gson.Gson; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | import javax.servlet.http.HttpServletRequest; 11 | 12 | public class GiteeWebhook implements IWebhook { 13 | private static final Logger LOG = LoggerFactory.getLogger(GiteeWebhook.class); 14 | @Override 15 | public String invokeCommand() { 16 | return "/gitee"; 17 | } 18 | 19 | @Override 20 | public Object handleWebhookPost(HttpServletRequest request, String user, String githubPayload, SendMessageCallback callback) { 21 | String event = request.getHeader("X-Gitee-Event"); 22 | LOG.info("on receive message {}, event {}", githubPayload, event); 23 | 24 | String message = null; 25 | 26 | //https://gitee.com/help/articles/4271#article-header0 27 | MessagePayload messagePayload = new MessagePayload(); 28 | messagePayload.setType(1); 29 | try { 30 | if (event.equals("Push Hook")) { 31 | PushOrTagHook pushOrTagHook = new Gson().fromJson(githubPayload, PushOrTagHook.class); 32 | message = pushOrTagHook.sender.name + " push " + pushOrTagHook.total_commits_count + " commits"; 33 | if (pushOrTagHook.commits != null) { 34 | for (Commit commit : pushOrTagHook.commits) { 35 | message += "\nCommit url: " + commit.url; 36 | message += "\nCommit message: " + commit.message; 37 | message += "\n"; 38 | } 39 | } 40 | } else if(event.equals("Tag Push Hook")) { 41 | PushOrTagHook pushOrTagHook = new Gson().fromJson(githubPayload, PushOrTagHook.class); 42 | message = pushOrTagHook.sender.name + (pushOrTagHook.created ? "创建了" : (pushOrTagHook.deleted ? "删除了":"更新了")) + " tag."; 43 | message += "\nTag: " + pushOrTagHook.compare; 44 | message += "\nRef: " + pushOrTagHook.ref; 45 | } else if(event.equals("Issue Hook")) { 46 | IssueHook issueHook = new Gson().fromJson(githubPayload, IssueHook.class); 47 | message = issueHook.sender.name + " " + issueHook.action + " issue."; 48 | message += "\nIssue:" + issueHook.issue.html_url; 49 | message += "\nMessage: " + issueHook.description; 50 | message += "\nStatus: " + issueHook.state; 51 | } else if(event.equals("Note Hook")) { 52 | NoteHook noteHook = new Gson().fromJson(githubPayload, NoteHook.class); 53 | message = noteHook.sender.name + " " + noteHook.action + " issue"; 54 | message += "\nIssue:" + noteHook.issue.html_url; 55 | message += "\nMessage: " + noteHook.note; 56 | message += "\nStatus: " + noteHook.issue.state; 57 | } else if(event.equals("Pull Request Hook")) { 58 | PullRequestHook pullRequestHook = new Gson().fromJson(githubPayload, PullRequestHook.class); 59 | message = pullRequestHook.sender.name + " " + pullRequestHook.action + "PR"; 60 | message += "\nPR: " + pullRequestHook.url; 61 | message += "\nTitle: " + pullRequestHook.title; 62 | message += "\nBody: " + pullRequestHook.body; 63 | } 64 | } catch (Exception e) { 65 | e.printStackTrace(); 66 | messagePayload.setSearchableContent("糟糕,处理gitee事件出错了:" + e.getMessage()); 67 | callback.sendMessage(messagePayload); 68 | } 69 | 70 | if (message == null) { 71 | messagePayload.setSearchableContent("你收到了一个gitee事件:" + event); 72 | callback.sendMessage(messagePayload); 73 | 74 | messagePayload.setSearchableContent(githubPayload); 75 | callback.sendMessage(messagePayload); 76 | } else { 77 | messagePayload.setSearchableContent(message); 78 | callback.sendMessage(messagePayload); 79 | } 80 | return "ok"; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/gitee/pojo/Branch.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.gitee.pojo; 2 | 3 | public class Branch { 4 | public String label; 5 | public String ref; 6 | public String sha; 7 | public User user; 8 | public Project repo; 9 | /* 10 | label: String, # 分支标记。eg:oschina:master 11 | ref: String, # 分支名。eg:master 12 | sha: String, # git 提交记录中 sha 值。eg:51b1acb1b4044fcdb2ff8a75ad15a4b655101754 13 | user: *user, # 分支所在仓库的所有者信息 14 | repo: *project # 分支所在仓库的信息 15 | */ 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/gitee/pojo/Commit.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.gitee.pojo; 2 | 3 | public class Commit { 4 | public String id; 5 | public String tree_id; 6 | public String[] parent_ids; 7 | public String message; 8 | public String timestamp; 9 | public String url; 10 | public User author; 11 | public User committer; 12 | public boolean distinct; 13 | public String[] added; 14 | public String[] removed; 15 | public String[] modified; 16 | // id: String, 17 | // tree_id: String, # commit tree oid。eg:db78f3594ec0683f5d857ef731df0d860f14f2b2 18 | // parent_ids: [String], # commit parent_ids。eg:['a3bddf21a35af54348aae5b0f5627e6ba35be51c'] 19 | // message: String, # commit 的信息。eg:fix(cache): 修复了缓存问题 20 | // timestamp: String, # commit 的时间。eg:2020-01-01T00:00:00+08:00 21 | // url: String, # commit 对应的 Gitee url。eg:https://gitee.com/mayun-team/oauth2_dingtalk/commit/664b34859fc4a924cd60be2592c0fc788fbeaf8f 22 | // author: *user, # 作者信息。 23 | // committer: *user, # 提交者信息。 24 | // distinct: Boolean, # 特殊的 commit,没任何改动,如 tag 25 | // added: [String] || null, # 新加入的文件名。eg:['README.md'] 26 | // removed: [String] || null, # 被移除的文件名。eg:['README.md'] 27 | // modified: [String] || null # 修改过的文件名。eg:['README.md'] 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/gitee/pojo/Enterprise.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.gitee.pojo; 2 | 3 | public class Enterprise { 4 | public String name; 5 | public String url; 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/gitee/pojo/Issue.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.gitee.pojo; 2 | 3 | public class Issue { 4 | public String html_url; 5 | public long id; 6 | public String number; 7 | public String title; 8 | public User user; 9 | public Label[] labels; 10 | public String state; 11 | public String state_name; 12 | public String type_name; 13 | public User assignee; 14 | public User[] collaborators; 15 | public Milestone milestone; 16 | public int comments; 17 | public String created_at; 18 | public String updated_at; 19 | public String body; 20 | /* 21 | html_url: String, # Gitee 上对应的 url。eg:https://gitee.com/oschina/git-osc/issues/1 22 | id: Number, 23 | number: String, # issue 对应的标识。eg:IG6E9 24 | title: String, # issue 标题。eg:这是一个 issue 标题 25 | user: *user, # issue 创建者。 26 | labels: [*label] || null, # issue 对应的标签。 27 | state: String, # issue 状态。eg:open 28 | state_name: String, # issue 状态名。eg:代办的 29 | type_name: String, # issue 类型。eg:任务 30 | assignee: *user || null, # issue 负责人。 31 | collaborators: [*user] || null, # issue 协助者。 32 | milestone: *milestone || null, # issue 所属的里程碑。 33 | comments: Number, # issue 的评论总数 34 | created_at: String, # issue 的创建时间。eg:2020-01-01T00:00:00+08:00 35 | updated_at: String, # issue 的更新时间。eg:2020-01-01T00:00:00+08:00 36 | body: String # issue 的内容体。eg:数据库优化... 37 | */ 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/gitee/pojo/IssueHook.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.gitee.pojo; 2 | 3 | import com.google.gson.Gson; 4 | 5 | public class IssueHook { 6 | public String hook_url; 7 | public String hook_name; 8 | public String password; 9 | public long timestamp; 10 | public String sign; 11 | public String action; 12 | public Issue issue; 13 | public Project repository; 14 | public Project project; 15 | public User sender; 16 | public User target_user; 17 | public User assignee; 18 | public User updated_by; 19 | public String iid; 20 | public String title; 21 | public String description; 22 | public String state; 23 | public String milestone; 24 | public String url; 25 | public Enterprise enterprise; 26 | /* 27 | hook_id: self.id, # 钩子 id。 28 | hook_url: hook_url, # 钩子路由。 29 | hook_name: String, # 钩子名,固定为 issue_hooks。 30 | password: String, # 钩子密码。eg:123456 31 | timestamp: Number, # 触发钩子的时间戳。eg: 1576754827988 32 | sign: String, # 钩子根据密钥计算的签名。eg: "rLEHLuZRIQHuTPeXMib9Czoq9dVXO4TsQcmQQHtjXHA=" 33 | action: String, # issue 状态。eg:open 34 | issue: *issue, # issue 信息。 35 | repository: *project || null, # 仓库信息。 36 | project: *project || null, # 仓库信息。 37 | sender: *user, # 触发 hook 的用户信息。 38 | target_user: *user || null, # 被委托处理 issue 的用户信息。 39 | user: *user, # issue 创建者。 40 | assignee: *user || null, # issue 负责人。 41 | updated_by: *user, # 触发 hook 的用户信息。 42 | iid: String, # issue 对应的标识。eg:IG6E9 43 | title: String, # issue 标题。eg:这是一个 issue 标题 44 | description: String, # issue 的内容体。eg:数据库优化... 45 | state: String, # issue 状态。eg:open 46 | milestone: String || null, # 里程碑的标题。eg:开源计划 47 | url: String, # issue 在 Gitee 上对应的 url。eg:https://gitee.com/oschina/git-osc/issues/1 48 | enterprise: *enterprise || null # issue 所属的企业信息。 49 | */ 50 | public static void main(String[] var0) { 51 | String str = "{\"action\":\"open\",\"issue\":{\"html_url\":\"https://gitee.com/heavyrain2012/test/issues/I35DB8\",\"id\":5289380,\"number\":\"I35DB8\",\"title\":\"test\",\"user\":{\"id\":8657970,\"name\":\"heavyrain2012\",\"email\":\"8657970+heavyrain2012@user.noreply.gitee.com\",\"username\":\"heavyrain2012\",\"user_name\":\"heavyrain2012\",\"url\":\"https://gitee.com/heavyrain2012\",\"login\":\"heavyrain2012\",\"avatar_url\":\"https://gitee.com/assets/no_portrait.png\",\"html_url\":\"https://gitee.com/heavyrain2012\",\"type\":\"User\",\"site_admin\":false},\"labels\":[],\"state\":\"open\",\"state_name\":\"待办的\",\"type_name\":\"任务\",\"assignee\":null,\"collaborators\":[],\"milestone\":null,\"comments\":0,\"created_at\":\"2021-02-03T16:07:03+08:00\",\"updated_at\":\"2021-02-03T16:07:03+08:00\",\"body\":\"### 该问题是怎么引起的?\\r\\n\\r\\n\\r\\n\\r\\n### 重现步骤\\r\\n\\r\\n\\r\\n\\r\\n### 报错信息\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\"},\"repository\":{\"id\":14074728,\"name\":\"test\",\"path\":\"test\",\"full_name\":\"heavyrain2012/test\",\"owner\":{\"id\":8657970,\"name\":\"heavyrain2012\",\"email\":\"8657970+heavyrain2012@user.noreply.gitee.com\",\"username\":\"heavyrain2012\",\"user_name\":\"heavyrain2012\",\"url\":\"https://gitee.com/heavyrain2012\",\"login\":\"heavyrain2012\",\"avatar_url\":\"https://gitee.com/assets/no_portrait.png\",\"html_url\":\"https://gitee.com/heavyrain2012\",\"type\":\"User\",\"site_admin\":false},\"private\":false,\"html_url\":\"https://gitee.com/heavyrain2012/test\",\"url\":\"https://gitee.com/heavyrain2012/test\",\"description\":\"test\",\"fork\":false,\"created_at\":\"2021-02-03T14:44:33+08:00\",\"updated_at\":\"2021-02-03T14:44:34+08:00\",\"pushed_at\":\"2021-02-03T14:44:34+08:00\",\"git_url\":\"git://gitee.com/heavyrain2012/test.git\",\"ssh_url\":\"git@gitee.com:heavyrain2012/test.git\",\"clone_url\":\"https://gitee.com/heavyrain2012/test.git\",\"svn_url\":\"svn://gitee.com/heavyrain2012/test\",\"git_http_url\":\"https://gitee.com/heavyrain2012/test.git\",\"git_ssh_url\":\"git@gitee.com:heavyrain2012/test.git\",\"git_svn_url\":\"svn://gitee.com/heavyrain2012/test\",\"homepage\":null,\"stargazers_count\":0,\"watchers_count\":1,\"forks_count\":0,\"language\":\"Java\",\"has_issues\":true,\"has_wiki\":true,\"has_pages\":false,\"license\":\"MIT\",\"open_issues_count\":1,\"default_branch\":\"master\",\"namespace\":\"heavyrain2012\",\"name_with_namespace\":\"heavyrain2012/test\",\"path_with_namespace\":\"heavyrain2012/test\"},\"project\":{\"id\":14074728,\"name\":\"test\",\"path\":\"test\",\"full_name\":\"heavyrain2012/test\",\"owner\":{\"id\":8657970,\"name\":\"heavyrain2012\",\"email\":\"8657970+heavyrain2012@user.noreply.gitee.com\",\"username\":\"heavyrain2012\",\"user_name\":\"heavyrain2012\",\"url\":\"https://gitee.com/heavyrain2012\",\"login\":\"heavyrain2012\",\"avatar_url\":\"https://gitee.com/assets/no_portrait.png\",\"html_url\":\"https://gitee.com/heavyrain2012\",\"type\":\"User\",\"site_admin\":false},\"private\":false,\"html_url\":\"https://gitee.com/heavyrain2012/test\",\"url\":\"https://gitee.com/heavyrain2012/test\",\"description\":\"test\",\"fork\":false,\"created_at\":\"2021-02-03T14:44:33+08:00\",\"updated_at\":\"2021-02-03T14:44:34+08:00\",\"pushed_at\":\"2021-02-03T14:44:34+08:00\",\"git_url\":\"git://gitee.com/heavyrain2012/test.git\",\"ssh_url\":\"git@gitee.com:heavyrain2012/test.git\",\"clone_url\":\"https://gitee.com/heavyrain2012/test.git\",\"svn_url\":\"svn://gitee.com/heavyrain2012/test\",\"git_http_url\":\"https://gitee.com/heavyrain2012/test.git\",\"git_ssh_url\":\"git@gitee.com:heavyrain2012/test.git\",\"git_svn_url\":\"svn://gitee.com/heavyrain2012/test\",\"homepage\":null,\"stargazers_count\":0,\"watchers_count\":1,\"forks_count\":0,\"language\":\"Java\",\"has_issues\":true,\"has_wiki\":true,\"has_pages\":false,\"license\":\"MIT\",\"open_issues_count\":1,\"default_branch\":\"master\",\"namespace\":\"heavyrain2012\",\"name_with_namespace\":\"heavyrain2012/test\",\"path_with_namespace\":\"heavyrain2012/test\"},\"sender\":{\"id\":8657970,\"name\":\"heavyrain2012\",\"email\":\"8657970+heavyrain2012@user.noreply.gitee.com\",\"username\":\"heavyrain2012\",\"user_name\":\"heavyrain2012\",\"url\":\"https://gitee.com/heavyrain2012\",\"login\":\"heavyrain2012\",\"avatar_url\":\"https://gitee.com/assets/no_portrait.png\",\"html_url\":\"https://gitee.com/heavyrain2012\",\"type\":\"User\",\"site_admin\":false},\"target_user\":null,\"user\":{\"id\":8657970,\"name\":\"heavyrain2012\",\"email\":\"8657970+heavyrain2012@user.noreply.gitee.com\",\"username\":\"heavyrain2012\",\"user_name\":\"heavyrain2012\",\"url\":\"https://gitee.com/heavyrain2012\",\"login\":\"heavyrain2012\",\"avatar_url\":\"https://gitee.com/assets/no_portrait.png\",\"html_url\":\"https://gitee.com/heavyrain2012\",\"type\":\"User\",\"site_admin\":false},\"assignee\":null,\"updated_by\":{\"id\":8657970,\"name\":\"heavyrain2012\",\"email\":\"8657970+heavyrain2012@user.noreply.gitee.com\",\"username\":\"heavyrain2012\",\"user_name\":\"heavyrain2012\",\"url\":\"https://gitee.com/heavyrain2012\",\"login\":\"heavyrain2012\",\"avatar_url\":\"https://gitee.com/assets/no_portrait.png\",\"html_url\":\"https://gitee.com/heavyrain2012\",\"type\":\"User\",\"site_admin\":false},\"iid\":\"I35DB8\",\"title\":\"test\",\"description\":\"### 该问题是怎么引起的?\\r\\n\\r\\n\\r\\n\\r\\n### 重现步骤\\r\\n\\r\\n\\r\\n\\r\\n### 报错信息\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\",\"state\":\"open\",\"milestone\":null,\"url\":\"https://gitee.com/heavyrain2012/test/issues/I35DB8\",\"enterprise\":null,\"hook_name\":\"issue_hooks\",\"hook_id\":548608,\"hook_url\":\"https://gitee.com/heavyrain2012/test/hooks/548608/edit\",\"password\":\"\",\"timestamp\":\"1612339623863\",\"sign\":\"\"}"; 52 | IssueHook noteHook = new Gson().fromJson(str, IssueHook.class); 53 | System.out.println(noteHook.action); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/gitee/pojo/Label.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.gitee.pojo; 2 | 3 | public class Label { 4 | public long id; 5 | public String name; 6 | public String color; 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/gitee/pojo/Milestone.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.gitee.pojo; 2 | 3 | public class Milestone { 4 | public String html_url; 5 | public long id; 6 | public long number; 7 | public String title; 8 | public String description; 9 | public int open_issues; 10 | public int closed_issues; 11 | public String state; 12 | public String created_at; 13 | public String updated_at; 14 | public String due_on; 15 | /* 16 | html_url: String, # Gitee 上对应的 url。eg:https://gitee.com/oschina/git-osc/milestones/1 17 | id: Number, 18 | number: Number, # 与上面的 id 一致 19 | title: String, # 里程碑的标题。eg:开源计划 20 | description: String || null, # 里程碑的详细描述。eg:走向世界 21 | open_issues: Number, # 开启状态的 issue 数量 22 | closed_issues: Number, # 关闭状态的 issue 数量 23 | state: String, # 里程碑的状态。eg:open 24 | created_at: String, # 里程碑创建的时间。eg:2020-01-01T00:00:00+08:00 25 | updated_at: String, # 里程碑更新的时间。eg:2020-01-01T00:00:00+08:00 26 | due_on: String || null # 里程碑结束的时间。eg:2020-01-01T00:00:00+08:00 27 | */ 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/gitee/pojo/Note.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.gitee.pojo; 2 | 3 | public class Note { 4 | public long id; 5 | public String body; 6 | public User user; 7 | public String created_at; 8 | public String updated_at; 9 | public String html_url; 10 | public String position; 11 | public String commit_id; 12 | // id: Number, 13 | // body: String, # 评论内容。eg:好的东西应该开源... 14 | // user: *user, # 评论的作者信息。 15 | // created_at: String, # 评论的创建时间。eg:2020-01-01T00:00:00+08:00 16 | // updated_at: String, # 评论的更新时间。eg:2020-11-11T11:11:11+08:00 17 | // html_url: String, # 这条评论在 Gitee 上的 url。eg:https://gitee.com/oschina/git-osc#note_1 18 | // [position: String], # 在代码 commit 评论中对应的代码位置。eg:76ec1c6df700af34ae5f8dd00bd7bcb56c1bd706_9_9 19 | // [commit_id: String] # 在代码 commit 评论中对应的 commit id。eg:611de62f634d353bb75a290f59fa238ff2d8d3c7 20 | //} 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/gitee/pojo/NoteHook.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.gitee.pojo; 2 | 3 | import com.google.gson.Gson; 4 | 5 | public class NoteHook { 6 | public String hook_url; 7 | public String hook_name; 8 | public String password; 9 | public long timestamp; 10 | public String sign; 11 | public String action; 12 | public Commit commit; 13 | public Project repository; 14 | public Project project; 15 | public User author; 16 | public User sender; 17 | public String url; 18 | public String note; 19 | public String noteable_type; 20 | public long noteable_id; 21 | public Issue issue; 22 | public PullRequest pullRequest; 23 | public String title; 24 | public String per_iid; 25 | public String short_commit_id; 26 | public Enterprise enterprise; 27 | /* 28 | hook_id: self.id, # 钩子 id。 29 | hook_url: hook_url, # 钩子路由。 30 | hook_name: String, # 钩子名,固定为 note_hooks。 31 | password: String, # 钩子密码。eg:123456 32 | timestamp: Number, # 触发钩子的时间戳。eg: 1576754827988 33 | sign: String, # 钩子根据密钥计算的签名。eg: "rLEHLuZRIQHuTPeXMib9Czoq9dVXO4TsQcmQQHtjXHA=" 34 | action: String, # 评论的动作。eg:comment 35 | comment: *note, # 评论的数据信息。 36 | repository: *project || null, # 评论所在仓库的信息。 37 | project: *project || null, # 评论所在仓库的信息。 38 | author: *user, # 评论的作者信息。 39 | sender: *user, # 评论的作者信息。 40 | url: String, # 这条评论在 Gitee 上的 url。eg:https://gitee.com/oschina/git-osc#note_1 41 | note: String, # 评论内容。eg:好的东西应该开源... 42 | noteable_type: String, # 被评论的目标类型。eg:Issue 43 | noteable_id: Number, # 被评论的目标 id。 44 | [issue: *issue], # 被评论的 Issue 信息。 45 | [pull_request: *pull_request], # 被评论的 PR 信息。 46 | title: String || null, # 被评论的目标标题。eg:这是一个 PR 标题 47 | per_iid: String, # 被评论的目标标识。eg:IG6E9 48 | short_commit_id: String || null, # 被平路的 commit 提交中的简短 sha。eg:51b1acb 49 | enterprise: *enterprise || null # 被评论的目标所在的企业信息。 50 | */ 51 | public static void main(String[] var0) { 52 | String str = "{\"action\":\"comment\",\"comment\":{\"id\":4227147,\"body\":\"aksdjfklads\",\"user\":{\"id\":8657970,\"name\":\"heavyrain2012\",\"email\":\"8657970+heavyrain2012@user.noreply.gitee.com\",\"username\":\"heavyrain2012\",\"user_name\":\"heavyrain2012\",\"url\":\"https://gitee.com/heavyrain2012\",\"login\":\"heavyrain2012\",\"avatar_url\":\"https://gitee.com/assets/no_portrait.png\",\"html_url\":\"https://gitee.com/heavyrain2012\",\"type\":\"User\",\"site_admin\":false},\"created_at\":\"2021-02-03T16:10:05+08:00\",\"updated_at\":\"2021-02-03T16:10:05+08:00\",\"html_url\":\"https://gitee.com/heavyrain2012/test/issues/I35DB8#note_4227147\"},\"repository\":{\"id\":14074728,\"name\":\"test\",\"path\":\"test\",\"full_name\":\"heavyrain2012/test\",\"owner\":{\"id\":8657970,\"name\":\"heavyrain2012\",\"email\":\"8657970+heavyrain2012@user.noreply.gitee.com\",\"username\":\"heavyrain2012\",\"user_name\":\"heavyrain2012\",\"url\":\"https://gitee.com/heavyrain2012\",\"login\":\"heavyrain2012\",\"avatar_url\":\"https://gitee.com/assets/no_portrait.png\",\"html_url\":\"https://gitee.com/heavyrain2012\",\"type\":\"User\",\"site_admin\":false},\"private\":false,\"html_url\":\"https://gitee.com/heavyrain2012/test\",\"url\":\"https://gitee.com/heavyrain2012/test\",\"description\":\"test\",\"fork\":false,\"created_at\":\"2021-02-03T14:44:33+08:00\",\"updated_at\":\"2021-02-03T16:07:03+08:00\",\"pushed_at\":\"2021-02-03T14:44:34+08:00\",\"git_url\":\"git://gitee.com/heavyrain2012/test.git\",\"ssh_url\":\"git@gitee.com:heavyrain2012/test.git\",\"clone_url\":\"https://gitee.com/heavyrain2012/test.git\",\"svn_url\":\"svn://gitee.com/heavyrain2012/test\",\"git_http_url\":\"https://gitee.com/heavyrain2012/test.git\",\"git_ssh_url\":\"git@gitee.com:heavyrain2012/test.git\",\"git_svn_url\":\"svn://gitee.com/heavyrain2012/test\",\"homepage\":null,\"stargazers_count\":0,\"watchers_count\":1,\"forks_count\":0,\"language\":\"Java\",\"has_issues\":true,\"has_wiki\":true,\"has_pages\":false,\"license\":\"MIT\",\"open_issues_count\":1,\"default_branch\":\"master\",\"namespace\":\"heavyrain2012\",\"name_with_namespace\":\"heavyrain2012/test\",\"path_with_namespace\":\"heavyrain2012/test\"},\"project\":{\"id\":14074728,\"name\":\"test\",\"path\":\"test\",\"full_name\":\"heavyrain2012/test\",\"owner\":{\"id\":8657970,\"name\":\"heavyrain2012\",\"email\":\"8657970+heavyrain2012@user.noreply.gitee.com\",\"username\":\"heavyrain2012\",\"user_name\":\"heavyrain2012\",\"url\":\"https://gitee.com/heavyrain2012\",\"login\":\"heavyrain2012\",\"avatar_url\":\"https://gitee.com/assets/no_portrait.png\",\"html_url\":\"https://gitee.com/heavyrain2012\",\"type\":\"User\",\"site_admin\":false},\"private\":false,\"html_url\":\"https://gitee.com/heavyrain2012/test\",\"url\":\"https://gitee.com/heavyrain2012/test\",\"description\":\"test\",\"fork\":false,\"created_at\":\"2021-02-03T14:44:33+08:00\",\"updated_at\":\"2021-02-03T16:07:03+08:00\",\"pushed_at\":\"2021-02-03T14:44:34+08:00\",\"git_url\":\"git://gitee.com/heavyrain2012/test.git\",\"ssh_url\":\"git@gitee.com:heavyrain2012/test.git\",\"clone_url\":\"https://gitee.com/heavyrain2012/test.git\",\"svn_url\":\"svn://gitee.com/heavyrain2012/test\",\"git_http_url\":\"https://gitee.com/heavyrain2012/test.git\",\"git_ssh_url\":\"git@gitee.com:heavyrain2012/test.git\",\"git_svn_url\":\"svn://gitee.com/heavyrain2012/test\",\"homepage\":null,\"stargazers_count\":0,\"watchers_count\":1,\"forks_count\":0,\"language\":\"Java\",\"has_issues\":true,\"has_wiki\":true,\"has_pages\":false,\"license\":\"MIT\",\"open_issues_count\":1,\"default_branch\":\"master\",\"namespace\":\"heavyrain2012\",\"name_with_namespace\":\"heavyrain2012/test\",\"path_with_namespace\":\"heavyrain2012/test\"},\"author\":{\"id\":8657970,\"name\":\"heavyrain2012\",\"email\":\"8657970+heavyrain2012@user.noreply.gitee.com\",\"username\":\"heavyrain2012\",\"user_name\":\"heavyrain2012\",\"url\":\"https://gitee.com/heavyrain2012\",\"login\":\"heavyrain2012\",\"avatar_url\":\"https://gitee.com/assets/no_portrait.png\",\"html_url\":\"https://gitee.com/heavyrain2012\",\"type\":\"User\",\"site_admin\":false},\"sender\":{\"id\":8657970,\"name\":\"heavyrain2012\",\"email\":\"8657970+heavyrain2012@user.noreply.gitee.com\",\"username\":\"heavyrain2012\",\"user_name\":\"heavyrain2012\",\"url\":\"https://gitee.com/heavyrain2012\",\"login\":\"heavyrain2012\",\"avatar_url\":\"https://gitee.com/assets/no_portrait.png\",\"html_url\":\"https://gitee.com/heavyrain2012\",\"type\":\"User\",\"site_admin\":false},\"url\":\"https://gitee.com/heavyrain2012/test/issues/I35DB8#note_4227147\",\"note\":\"aksdjfklads\",\"noteable_type\":\"Issue\",\"noteable_id\":5289380,\"title\":\"test\",\"per_iid\":\"#I35DB8\",\"short_commit_id\":\"\",\"enterprise\":null,\"issue\":{\"html_url\":\"https://gitee.com/heavyrain2012/test/issues/I35DB8\",\"id\":5289380,\"number\":\"I35DB8\",\"title\":\"test\",\"user\":{\"id\":8657970,\"name\":\"heavyrain2012\",\"email\":\"8657970+heavyrain2012@user.noreply.gitee.com\",\"username\":\"heavyrain2012\",\"user_name\":\"heavyrain2012\",\"url\":\"https://gitee.com/heavyrain2012\",\"login\":\"heavyrain2012\",\"avatar_url\":\"https://gitee.com/assets/no_portrait.png\",\"html_url\":\"https://gitee.com/heavyrain2012\",\"type\":\"User\",\"site_admin\":false},\"labels\":[],\"state\":\"open\",\"state_name\":\"待办的\",\"type_name\":\"任务\",\"assignee\":null,\"collaborators\":[],\"milestone\":null,\"comments\":1,\"created_at\":\"2021-02-03T16:07:03+08:00\",\"updated_at\":\"2021-02-03T16:10:05+08:00\",\"body\":\"### 该问题是怎么引起的?\\r\\n\\r\\n\\r\\n\\r\\n### 重现步骤\\r\\n\\r\\n\\r\\n\\r\\n### 报错信息\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\"},\"hook_name\":\"note_hooks\",\"hook_id\":548608,\"hook_url\":\"https://gitee.com/heavyrain2012/test/hooks/548608/edit\",\"password\":\"\",\"timestamp\":\"1612339806012\",\"sign\":\"\"}"; 53 | NoteHook noteHook = new Gson().fromJson(str, NoteHook.class); 54 | System.out.println(noteHook.action); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/gitee/pojo/Project.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.gitee.pojo; 2 | 3 | public class Project { 4 | public long id; 5 | public String name; 6 | public String path; 7 | public String full_name; 8 | public User owner; 9 | // public boolean private; 10 | public String html_url; 11 | public String url; 12 | public String description; 13 | public boolean fork; 14 | public String created_at; 15 | public String updated_at; 16 | public String pushed_at; 17 | public String git_url; 18 | public String ssh_url; 19 | public String clone_url; 20 | public String svn_url; 21 | public String git_http_url; 22 | public String git_ssh_url; 23 | public String git_svn_ur; 24 | public String homepage; 25 | public int stargazers_count; 26 | public int watchers_count; 27 | public int forks_count; 28 | public String language; 29 | public boolean has_issues; 30 | public boolean has_wiki; 31 | public boolean has_pages; 32 | public String license; 33 | public int open_issues_count; 34 | public String default_branch; 35 | public String namespace; 36 | public String name_with_namespace; 37 | public String path_with_namespace; 38 | /* 39 | id: Number, 40 | name: String, # 仓库名。eg:gitee 41 | path: String, # 仓库所属的空间地址。eg:oschian 42 | full_name: String, # 完整的名字,name + path。eg:gitee/oschian 43 | owner: *user, # 仓库的所有者。 44 | private: Boolean, # 是否公开。 45 | html_url: String, # 对应 Gitee 的 url。eg:https://gitee.com/oschina/git-osc 46 | url: String, # 与上面 html_url 一致 47 | description: String, # 仓库描述。eg:这是一个开源仓库... 48 | fork: Boolean, # 是不是 fork 仓库。 49 | created_at: String, # 仓库的创建时间。eg:2020-01-01T00:00:00+08:00 50 | updated_at: String, # 仓库的更新时间。eg:2020-01-01T00:00:00+08:00 51 | pushed_at: String, # 仓库的最近一次推送时间。eg:2020-01-01T00:00:00+08:00 52 | git_url: String, # 仓库的 git 地址。eg:git://gitee.com:oschina/git-osc.git 53 | ssh_url: String, # 仓库的 ssh 地址。eg:git@gitee.com:oschina/git-osc.git 54 | clone_url: String, # 仓库的 clone 地址。eg:https://gitee.com/oschina/git-osc.git 55 | svn_url: String, # 仓库的 svn 地址。eg:svn://gitee.com/oschina/git-osc 56 | git_http_url: String, # 与上面的 clone_url 一致。 57 | git_ssh_url: String, # 与上面的 ssh_url 一致。 58 | git_svn_url: String, # 与上面的 svn_url 一致。 59 | homepage: String || null, # 仓库的网页主页。eg:https://gitee.com 60 | stargazers_count: Number, # 仓库的 star 数量。 61 | watchers_count: Number, # 仓库的 watch 数量。 62 | forks_count: Number, # 仓库的 fork 数量。 63 | language: String, # 仓库的编程语言。eg: Ruby 64 | has_issues: Boolean, # 仓库的是否开启了 issue 功能。 65 | has_wiki: Boolean, # 仓库的是否开启了 wiki 功能。 66 | has_pages: Boolean, # 仓库的是否开启了 page 服务。 67 | license: String || null, # 仓库的开源协议。eg:MIT 68 | open_issues_count: Number, # 仓库开启状态的 issue 总数。 69 | default_branch: String, # 仓库的默认复制。eg:master 70 | namespace: String, # 仓库所属的 Gitee 地址。eg:oschina 71 | name_with_namespace: String, # 与上面的 full_name 一致。 72 | path_with_namespace: String # 仓库的在 Gitee 的资源唯一标识。eg:oschia/git-osc 73 | */ 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/gitee/pojo/PullRequest.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.gitee.pojo; 2 | 3 | public class PullRequest { 4 | public long id; 5 | public long number; 6 | public String state; 7 | public String html_url; 8 | public String diff_url; 9 | public String patch_url; 10 | public String title; 11 | public String body; 12 | public String created_at; 13 | public String updated_at; 14 | public String closed_at; 15 | public String merged_at; 16 | public String merge_commit_sha; 17 | public String merge_refreence_name; 18 | public User user; 19 | public User assignee; 20 | public User[] assignees; 21 | public User tester; 22 | public User[] testers; 23 | public boolean need_test; 24 | public boolean need_review; 25 | public Milestone milestone; 26 | public Branch head; 27 | public Branch base; 28 | public boolean merged; 29 | public boolean mergeable; 30 | public String merge_status; 31 | public User updated_by; 32 | public int comments; 33 | public int commits; 34 | public int additions; 35 | public int deletions; 36 | public int changed_files; 37 | /*id: Number, 38 | number: Number, # 与上面 id 一致 39 | state: String, # PR 状态。eg:open 40 | html_url: String, # PR 在 Gitee 上 url。eg:https://gitee.com/oschina/pulls/1 41 | diff_url: String, # PR diff 信息 url。eg:https://gitee.com/oschina/pulls/1.diff 42 | patch_url: String, # PR patch 信息 url。eg:https://gitee.com/oschina/pulls/1.patch 43 | title: String, # PR 的标题。eg:这是一个 PR 标题 44 | body: String || null, # PR 的内容。eg:升级服务... 45 | created_at: String, # PR 的创建时间。eg:2020-01-01T00:00:00+08:00 46 | updated_at: String, # PR 的更新时间。eg:2020-01-01T00:00:00+08:00 47 | closed_at: String || null, # PR 的关闭时间。eg:2020-01-01T00:00:00+08:00 48 | merged_at: String || null, # PR 的合并时间。eg:2020-01-01T00:00:00+08:00 49 | merge_commit_sha: String || null, # PR 合并产生的 commit id。eg:51b1acb1b4044fcdb2ff8a75ad15a4b655101754 50 | merge_reference_name: String, # PR 的源分支目标。eg:refs/pull/1/MERGE 51 | user: *user, # PR 的创建者。 52 | assignee: *user || null, # PR 的负责人。 53 | assignees: [*user] || null, # PR 的审核人。 54 | tester: *user || null, # PR 的测试者。 55 | testers: [*user] || null, # PR 的所有测试者。 56 | need_test: Boolean, # PR 是否需要测试。 57 | need_review: Boolean, # PR 是否需要审核。 58 | milestone: *milestone || null, # PR 所属的里程碑。 59 | head: *branch || null, # PR 的源分支。 60 | base: *branch, # PR 要合并的目标分支 61 | merged: Boolean, # PR 是否已合并。 62 | mergeable: Boolean, # PR 是否可以合并。 63 | merge_status: String, # PR 的合并状态。eg:unchecked 64 | updated_by: *user || null, # PR 的修改者。 65 | comments: Number, # PR 的总评论数量。 66 | commits: Number, # PR 的总 commit 数量。 67 | additions: Number, # PR 新增了多少行。 68 | deletions: Number, # PR 删除了多少行。 69 | changed_files: Number # PR 修改了多少行。 70 | */ 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/gitee/pojo/PullRequestHook.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.gitee.pojo; 2 | 3 | public class PullRequestHook { 4 | public String hook_url; 5 | public String hook_name; 6 | public String password; 7 | public long timestamp; 8 | public String sign; 9 | public String action; 10 | public PullRequest pull_request; 11 | public long number; 12 | public long iid; 13 | public String title; 14 | public String body; 15 | public String state; 16 | public String merge_status; 17 | public String merge_commit_sha; 18 | public String url; 19 | public String source_branch; 20 | public String target_branch; 21 | public Project project; 22 | public Project repository; 23 | public User author; 24 | public User updated_by; 25 | public User sender; 26 | public User target_user; 27 | public Enterprise enterprise; 28 | /* 29 | hook_id: self.id, # 钩子 id。 30 | hook_url: hook_url, # 钩子路由。 31 | hook_name: String, # 钩子名,固定为 merge_request_hooks。 32 | password: String, # 钩子密码。eg:123456 33 | timestamp: Number, # 触发钩子的时间戳。eg: 1576754827988 34 | sign: String, # 钩子根据密钥计算的签名。eg: "rLEHLuZRIQHuTPeXMib9Czoq9dVXO4TsQcmQQHtjXHA=" 35 | action: String, # PR 状态。eg:open 36 | pull_request: *pull_request, # PR 的信息。 37 | number: Number, # PR 的 id。 38 | iid: Number, # 与上面 number 一致。 39 | title: String, # PR 的标题。eg:这是一个 PR 标题 40 | body: String || nil, # PR 的内容。eg:升级服务... 41 | state: String, # PR 状态。eg:open 42 | merge_status: String, # PR 的合并状态。eg:unchecked 43 | merge_commit_sha: String, # PR 合并产生的 commit id。eg:51b1acb1b4044fcdb2ff8a75ad15a4b655101754 44 | url: String, # PR 在 Gitee 上 url。eg:https://gitee.com/oschina/pulls/1 45 | source_branch: String || null, # PR 的源分支名。eg:fixbug 46 | source_repo: { 47 | project: *project, # PR 的源仓库信息。 48 | repository: *project # PR 的源仓库信息。 49 | } || null, 50 | target_branch: String, # PR 的目标分支名。master 51 | target_repo: { 52 | project: *project, # PR 的目标仓库信息。 53 | repository: *project # PR 的目标仓库信息。 54 | }, 55 | project: *project, # PR 的目标仓库信息。 56 | repository: *project, # PR 的目标仓库信息。 57 | author: *user, # PR 的创建者信息。 58 | updated_by: *user, # PR 的更新者信息。 59 | sender: *user, # PR 的更新者信息。 60 | target_user: *user || null, # 被委托处理 PR 的用户信息。 61 | enterprise: *enterprise || null # PR 仓库所在的企业信息。 62 | */ 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/gitee/pojo/PushOrTagHook.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.gitee.pojo; 2 | 3 | public class PushOrTagHook { 4 | public String hook_url; 5 | public String hook_name; 6 | public String password; 7 | public long timestamp; 8 | public String sign; 9 | public String ref; 10 | public String before; 11 | public String after; 12 | public int total_commits_count; 13 | public boolean commits_more_than_ten; 14 | public boolean created; 15 | public boolean deleted; 16 | public String compare; 17 | public Commit[] commits; 18 | public Commit head_commit; 19 | public Project repository; 20 | public Project project; 21 | public long user_id; 22 | public String user_name; 23 | public User user; 24 | public User pusher; 25 | public User sender; 26 | public Enterprise enterprise; 27 | /* 28 | hook_id: self.id, # 钩子 id。 29 | hook_url: hook_url, # 钩子路由。 30 | hook_name: String, # 钩子名,固定为 push_hooks/tag_push_hooks。 31 | password: String, # 钩子密码。eg:123456 32 | timestamp: Number, # 触发钩子的时间戳。eg: 1576754827988 33 | sign: String, # 钩子根据密钥计算的签名。eg: "rLEHLuZRIQHuTPeXMib9Czoq9dVXO4TsQcmQQHtjXHA=" 34 | ref: String, # 推送的分支。eg:refs/heads/master 35 | before: String, # 推送前分支的 commit id。eg:5221c062df39e9e477ab015df22890b7bf13fbbd 36 | after: String, # 推送后分支的 commit id。eg:1cdcd819599cbb4099289dbbec762452f006cb40 37 | [total_commits_count: Number], # 推送包含的 commit 总数。 38 | [commits_more_than_ten: Boolean], # 推送包含的 commit 总数是否大于十二。 39 | created: Boolean, # 推送的是否是新分支。 40 | deleted: Boolean, # 推送的是否是删除分支。 41 | compare: String, # 推送的 commit 差异 url。eg:https://gitee.com/oschina/git-osc/compare/5221c062df39e9e477ab015df22890b7bf13fbbd...1cdcd819599cbb4099289dbbec762452f006cb40 42 | commits: [*commit] || null, # 推送的全部 commit 信息。 43 | head_commit: commit, # 推送最前面的 commit 信息。 44 | repository: *project, # 推送的目标仓库信息。 45 | project: *project, # 推送的目标仓库信息。 46 | user_id: Number, 47 | user_name: String, # 推送者的昵称。 48 | user: *user, # 推送者的用户信息。 49 | pusher: *user, # 推送者的用户信息。 50 | sender: *user, # 推送者的用户信息。 51 | enterprise: *enterprise || ull # 推送的目标仓库所在的企业信息。 52 | */ 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/gitee/pojo/User.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.gitee.pojo; 2 | 3 | public class User { 4 | public long id; 5 | public String name; 6 | public String email; 7 | public String username; 8 | public String user_name; 9 | public String url; 10 | public String login; 11 | public String avatar_url; 12 | public String html_url; 13 | public String type; 14 | public String site_admin; 15 | public String time; 16 | public String remark; 17 | // [id: Number], 18 | // name: String, # 用户的昵称。eg:红薯 19 | // email: String, # 用户的邮箱。eg:git@oschina.cn 20 | // [username: String], # 用户的 Gitee 个人空间地址。eg:gitee 21 | // [user_name: String], # 与上面的 username 一致。 22 | // [url: String], # 用户的 Gitee 个人主页 url。eg:https://gitee.com/gitee 23 | // [login: String], # 与上面的 username 一致。 24 | // [avatar_url: String || null], # 用户头像 url。eg:https://gitee.com/assets/favicon.ico 25 | // [html_url: String], # 与上面的 url 一致。 26 | // [type: String], # 用户类型,目前固定为 User。 27 | // [site_admin: Boolean], # 是不是管理员。 28 | // [time: String], # git commit 中的时间。eg:2020-01-01T00:00:00+08:00 29 | // [remark: String] # 用户备注名。eg:Ruby 大神 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/github/GithubWebhook.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.github; 2 | 3 | import cn.wildfirechat.app.webhook.IWebhook; 4 | import cn.wildfirechat.app.webhook.github.pojo.*; 5 | import cn.wildfirechat.pojos.MessagePayload; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import javax.servlet.http.HttpServletRequest; 10 | 11 | public class GithubWebhook implements IWebhook { 12 | private static final Logger LOG = LoggerFactory.getLogger(GithubWebhook.class); 13 | @Override 14 | public String invokeCommand() { 15 | return "/github"; 16 | } 17 | 18 | @Override 19 | public Object handleWebhookPost(HttpServletRequest request, String user, String githubPayload, SendMessageCallback callback) { 20 | String event = request.getHeader("X-GitHub-Event"); 21 | LOG.info("on receive message {}", githubPayload); 22 | 23 | String message = null; 24 | 25 | MessagePayload messagePayload = new MessagePayload(); 26 | messagePayload.setType(1); 27 | try { 28 | if (event.equals("push")) { 29 | PushEvent pushEvent = PushEvent.fromJson(githubPayload); 30 | message = "用户 " + pushEvent.pusher.name + " 在仓库 " + pushEvent.repository.full_name + " 提交了代码\n"; 31 | for (Commit commit : pushEvent.commits) { 32 | message += "提交描述: " + commit.message + " 修改代码: " + commit.url + " \n"; 33 | } 34 | } else if(event.equals("issues")) { 35 | IssueEvent issueEvent = IssueEvent.fromJson(githubPayload); 36 | message = "用户 " + issueEvent.sender.login + " 在仓库 " + issueEvent.repository.full_name + " " + issueEvent.action + " issue\n"; 37 | message += issueEvent.issue.html_url + " \n"; 38 | message += issueEvent.issue.title + " : " + issueEvent.issue.body; 39 | } else if(event.equals("star")) { 40 | StarEvent starEvent = StarEvent.fromJson(githubPayload); 41 | if (starEvent.action.equals("created")) { 42 | message = "用户 " + starEvent.sender.login + " star 了工程 " + starEvent.repository.full_name + " \n"; 43 | } else { 44 | message = "用户 " + starEvent.sender.login + " unstar 了工程 " + starEvent.repository.full_name + " \n"; 45 | } 46 | message += "现有star数: " + starEvent.repository.stargazers_count; 47 | } else if(event.equals("issue_comment")) { 48 | IssueCommentEvent issueCommentEvent = IssueCommentEvent.fromJson(githubPayload); 49 | if (issueCommentEvent.action.equals("created")) { 50 | message = "用户 " + issueCommentEvent.sender.login + " 评论了issue " + issueCommentEvent.repository.full_name + " : " + issueCommentEvent.issue.title + " \n"; 51 | message += "内容: " + issueCommentEvent.comment.body + " \n"; 52 | } else if (issueCommentEvent.action.equals("edited")) { 53 | message = "用户 " + issueCommentEvent.sender.login + " 修改了issue " + issueCommentEvent.repository.full_name + " : " + issueCommentEvent.issue.title + " 的评论\n"; 54 | message += "修改内容: " + issueCommentEvent.comment.body + " \n"; 55 | } else { 56 | message = "用户 " + issueCommentEvent.sender.login + " 删除了issue " + issueCommentEvent.repository.full_name + " 的评论\n"; 57 | } 58 | message += "issue链接: " + issueCommentEvent.issue.html_url; 59 | } else if(event.equals("fork")) { 60 | ForkEvent forkEvent = ForkEvent.fromJson(githubPayload); 61 | if (forkEvent.forkee.fork) { 62 | message = "用户 " + forkEvent.sender.login + " fork 了工程 " + forkEvent.repository.full_name + " \n"; 63 | } else { 64 | message = "用户 " + forkEvent.sender.login + " unfork 了工程 " + forkEvent.repository.full_name + " \n"; 65 | } 66 | message += "现有star数: " + forkEvent.repository.stargazers_count + "。 现在的fork数: " + forkEvent.repository.forks_count; 67 | } else if(event.equals("watch")) { 68 | WatchEvent watchEvent = WatchEvent.fromJson(githubPayload); 69 | message = "用户 " + watchEvent.sender.login + " watch 了工程 " + watchEvent.repository.full_name + " \n"; 70 | } else if(event.equals("ping")) { 71 | PingEvent pingEvent = PingEvent.fromJson(githubPayload); 72 | message = "Ping to " + pingEvent.repository.full_name; 73 | } else if(event.equals("pull_request")) { 74 | PullRequestEvent pullRequestEvent = PullRequestEvent.fromJson(githubPayload); 75 | message = "User " + pullRequestEvent.sender.login + " pull request:" + pullRequestEvent.repository.full_name + "。\nTitle:" + pullRequestEvent.pull_request.title + "\nbody:" + pullRequestEvent.pull_request.body + "\nurl:" + pullRequestEvent.pull_request.html_url; 76 | } 77 | } catch (Exception e) { 78 | e.printStackTrace(); 79 | messagePayload.setSearchableContent("糟糕,处理github事件出错了:" + e.getMessage()); 80 | callback.sendMessage(messagePayload); 81 | } 82 | 83 | if (message == null) { 84 | messagePayload.setSearchableContent("你收到了一个github事件:" + event); 85 | callback.sendMessage(messagePayload); 86 | messagePayload.setSearchableContent(githubPayload); 87 | callback.sendMessage(messagePayload); 88 | } else { 89 | messagePayload.setSearchableContent(message); 90 | callback.sendMessage(messagePayload); 91 | } 92 | return "ok"; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/github/pojo/Comment.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.github.pojo; 2 | 3 | public class Comment { 4 | public String url; 5 | public String html_url; 6 | public String issue_url; 7 | public long id; 8 | public String node_id; 9 | public User user; 10 | public String body; 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/github/pojo/Commit.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.github.pojo; 2 | 3 | import java.util.Date; 4 | 5 | public class Commit { 6 | public String id; 7 | public String tree_id; 8 | public Date timestamp; 9 | public String sha; 10 | public String message; 11 | public Pusher author; 12 | public String url; 13 | public boolean distinct; 14 | public String[] added; 15 | public String[] removed; 16 | public String[] modified; 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/github/pojo/ForkEvent.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.github.pojo; 2 | 3 | import com.google.gson.Gson; 4 | 5 | public class ForkEvent { 6 | public Forkee forkee; 7 | public Repository repository; 8 | public User sender; 9 | 10 | public static ForkEvent fromJson(String jsonStr) { 11 | return new Gson().fromJson(jsonStr, ForkEvent.class); 12 | } 13 | public static void main(String[] args) { 14 | String event1 = "{\"forkee\":{\"id\":242609213,\"node_id\":\"MDEwOlJlcG9zaXRvcnkyNDI2MDkyMTM=\",\"name\":\"server\",\"full_name\":\"yangwugui/server\",\"private\":false,\"owner\":{\"login\":\"yangwugui\",\"id\":9507380,\"node_id\":\"MDQ6VXNlcjk1MDczODA=\",\"avatar_url\":\"https://avatars3.githubusercontent.com/u/9507380?v=4\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/yangwugui\",\"html_url\":\"https://github.com/yangwugui\",\"followers_url\":\"https://api.github.com/users/yangwugui/followers\",\"following_url\":\"https://api.github.com/users/yangwugui/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/yangwugui/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/yangwugui/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/yangwugui/subscriptions\",\"organizations_url\":\"https://api.github.com/users/yangwugui/orgs\",\"repos_url\":\"https://api.github.com/users/yangwugui/repos\",\"events_url\":\"https://api.github.com/users/yangwugui/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/yangwugui/received_events\",\"type\":\"User\",\"site_admin\":false},\"html_url\":\"https://github.com/yangwugui/server\",\"description\":\"即时通讯(IM)系统\",\"fork\":true,\"url\":\"https://api.github.com/repos/yangwugui/server\",\"forks_url\":\"https://api.github.com/repos/yangwugui/server/forks\",\"keys_url\":\"https://api.github.com/repos/yangwugui/server/keys{/key_id}\",\"collaborators_url\":\"https://api.github.com/repos/yangwugui/server/collaborators{/collaborator}\",\"teams_url\":\"https://api.github.com/repos/yangwugui/server/teams\",\"hooks_url\":\"https://api.github.com/repos/yangwugui/server/hooks\",\"issue_events_url\":\"https://api.github.com/repos/yangwugui/server/issues/events{/number}\",\"events_url\":\"https://api.github.com/repos/yangwugui/server/events\",\"assignees_url\":\"https://api.github.com/repos/yangwugui/server/assignees{/user}\",\"branches_url\":\"https://api.github.com/repos/yangwugui/server/branches{/branch}\",\"tags_url\":\"https://api.github.com/repos/yangwugui/server/tags\",\"blobs_url\":\"https://api.github.com/repos/yangwugui/server/git/blobs{/sha}\",\"git_tags_url\":\"https://api.github.com/repos/yangwugui/server/git/tags{/sha}\",\"git_refs_url\":\"https://api.github.com/repos/yangwugui/server/git/refs{/sha}\",\"trees_url\":\"https://api.github.com/repos/yangwugui/server/git/trees{/sha}\",\"statuses_url\":\"https://api.github.com/repos/yangwugui/server/statuses/{sha}\",\"languages_url\":\"https://api.github.com/repos/yangwugui/server/languages\",\"stargazers_url\":\"https://api.github.com/repos/yangwugui/server/stargazers\",\"contributors_url\":\"https://api.github.com/repos/yangwugui/server/contributors\",\"subscribers_url\":\"https://api.github.com/repos/yangwugui/server/subscribers\",\"subscription_url\":\"https://api.github.com/repos/yangwugui/server/subscription\",\"commits_url\":\"https://api.github.com/repos/yangwugui/server/commits{/sha}\",\"git_commits_url\":\"https://api.github.com/repos/yangwugui/server/git/commits{/sha}\",\"comments_url\":\"https://api.github.com/repos/yangwugui/server/comments{/number}\",\"issue_comment_url\":\"https://api.github.com/repos/yangwugui/server/issues/comments{/number}\",\"contents_url\":\"https://api.github.com/repos/yangwugui/server/contents/{+path}\",\"compare_url\":\"https://api.github.com/repos/yangwugui/server/compare/{base}...{head}\",\"merges_url\":\"https://api.github.com/repos/yangwugui/server/merges\",\"archive_url\":\"https://api.github.com/repos/yangwugui/server/{archive_format}{/ref}\",\"downloads_url\":\"https://api.github.com/repos/yangwugui/server/downloads\",\"issues_url\":\"https://api.github.com/repos/yangwugui/server/issues{/number}\",\"pulls_url\":\"https://api.github.com/repos/yangwugui/server/pulls{/number}\",\"milestones_url\":\"https://api.github.com/repos/yangwugui/server/milestones{/number}\",\"notifications_url\":\"https://api.github.com/repos/yangwugui/server/notifications{?since,all,participating}\",\"labels_url\":\"https://api.github.com/repos/yangwugui/server/labels{/name}\",\"releases_url\":\"https://api.github.com/repos/yangwugui/server/releases{/id}\",\"deployments_url\":\"https://api.github.com/repos/yangwugui/server/deployments\",\"created_at\":\"2020-02-23T23:40:41Z\",\"updated_at\":\"2020-02-23T03:38:30Z\",\"pushed_at\":\"2020-02-21T03:20:03Z\",\"git_url\":\"git://github.com/yangwugui/server.git\",\"ssh_url\":\"git@github.com:yangwugui/server.git\",\"clone_url\":\"https://github.com/yangwugui/server.git\",\"svn_url\":\"https://github.com/yangwugui/server\",\"homepage\":\"http://docs.wildfirechat.cn\",\"size\":8928,\"stargazers_count\":0,\"watchers_count\":0,\"language\":null,\"has_issues\":false,\"has_projects\":true,\"has_downloads\":true,\"has_wiki\":true,\"has_pages\":false,\"forks_count\":0,\"mirror_url\":null,\"archived\":false,\"disabled\":false,\"open_issues_count\":0,\"license\":{\"key\":\"other\",\"name\":\"Other\",\"spdx_id\":\"NOASSERTION\",\"url\":null,\"node_id\":\"MDc6TGljZW5zZTA=\"},\"forks\":0,\"open_issues\":0,\"watchers\":0,\"default_branch\":\"master\",\"public\":true},\"repository\":{\"id\":167204613,\"node_id\":\"MDEwOlJlcG9zaXRvcnkxNjcyMDQ2MTM=\",\"name\":\"server\",\"full_name\":\"wildfirechat/server\",\"private\":false,\"owner\":{\"login\":\"wildfirechat\",\"id\":33191460,\"node_id\":\"MDEyOk9yZ2FuaXphdGlvbjMzMTkxNDYw\",\"avatar_url\":\"https://avatars0.githubusercontent.com/u/33191460?v=4\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/wildfirechat\",\"html_url\":\"https://github.com/wildfirechat\",\"followers_url\":\"https://api.github.com/users/wildfirechat/followers\",\"following_url\":\"https://api.github.com/users/wildfirechat/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/wildfirechat/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/wildfirechat/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/wildfirechat/subscriptions\",\"organizations_url\":\"https://api.github.com/users/wildfirechat/orgs\",\"repos_url\":\"https://api.github.com/users/wildfirechat/repos\",\"events_url\":\"https://api.github.com/users/wildfirechat/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/wildfirechat/received_events\",\"type\":\"Organization\",\"site_admin\":false},\"html_url\":\"https://github.com/wildfirechat/server\",\"description\":\"即时通讯(IM)系统\",\"fork\":false,\"url\":\"https://api.github.com/repos/wildfirechat/server\",\"forks_url\":\"https://api.github.com/repos/wildfirechat/server/forks\",\"keys_url\":\"https://api.github.com/repos/wildfirechat/server/keys{/key_id}\",\"collaborators_url\":\"https://api.github.com/repos/wildfirechat/server/collaborators{/collaborator}\",\"teams_url\":\"https://api.github.com/repos/wildfirechat/server/teams\",\"hooks_url\":\"https://api.github.com/repos/wildfirechat/server/hooks\",\"issue_events_url\":\"https://api.github.com/repos/wildfirechat/server/issues/events{/number}\",\"events_url\":\"https://api.github.com/repos/wildfirechat/server/events\",\"assignees_url\":\"https://api.github.com/repos/wildfirechat/server/assignees{/user}\",\"branches_url\":\"https://api.github.com/repos/wildfirechat/server/branches{/branch}\",\"tags_url\":\"https://api.github.com/repos/wildfirechat/server/tags\",\"blobs_url\":\"https://api.github.com/repos/wildfirechat/server/git/blobs{/sha}\",\"git_tags_url\":\"https://api.github.com/repos/wildfirechat/server/git/tags{/sha}\",\"git_refs_url\":\"https://api.github.com/repos/wildfirechat/server/git/refs{/sha}\",\"trees_url\":\"https://api.github.com/repos/wildfirechat/server/git/trees{/sha}\",\"statuses_url\":\"https://api.github.com/repos/wildfirechat/server/statuses/{sha}\",\"languages_url\":\"https://api.github.com/repos/wildfirechat/server/languages\",\"stargazers_url\":\"https://api.github.com/repos/wildfirechat/server/stargazers\",\"contributors_url\":\"https://api.github.com/repos/wildfirechat/server/contributors\",\"subscribers_url\":\"https://api.github.com/repos/wildfirechat/server/subscribers\",\"subscription_url\":\"https://api.github.com/repos/wildfirechat/server/subscription\",\"commits_url\":\"https://api.github.com/repos/wildfirechat/server/commits{/sha}\",\"git_commits_url\":\"https://api.github.com/repos/wildfirechat/server/git/commits{/sha}\",\"comments_url\":\"https://api.github.com/repos/wildfirechat/server/comments{/number}\",\"issue_comment_url\":\"https://api.github.com/repos/wildfirechat/server/issues/comments{/number}\",\"contents_url\":\"https://api.github.com/repos/wildfirechat/server/contents/{+path}\",\"compare_url\":\"https://api.github.com/repos/wildfirechat/server/compare/{base}...{head}\",\"merges_url\":\"https://api.github.com/repos/wildfirechat/server/merges\",\"archive_url\":\"https://api.github.com/repos/wildfirechat/server/{archive_format}{/ref}\",\"downloads_url\":\"https://api.github.com/repos/wildfirechat/server/downloads\",\"issues_url\":\"https://api.github.com/repos/wildfirechat/server/issues{/number}\",\"pulls_url\":\"https://api.github.com/repos/wildfirechat/server/pulls{/number}\",\"milestones_url\":\"https://api.github.com/repos/wildfirechat/server/milestones{/number}\",\"notifications_url\":\"https://api.github.com/repos/wildfirechat/server/notifications{?since,all,participating}\",\"labels_url\":\"https://api.github.com/repos/wildfirechat/server/labels{/name}\",\"releases_url\":\"https://api.github.com/repos/wildfirechat/server/releases{/id}\",\"deployments_url\":\"https://api.github.com/repos/wildfirechat/server/deployments\",\"created_at\":\"2019-01-23T15:21:28Z\",\"updated_at\":\"2020-02-23T03:38:30Z\",\"pushed_at\":\"2020-02-21T03:20:03Z\",\"git_url\":\"git://github.com/wildfirechat/server.git\",\"ssh_url\":\"git@github.com:wildfirechat/server.git\",\"clone_url\":\"https://github.com/wildfirechat/server.git\",\"svn_url\":\"https://github.com/wildfirechat/server\",\"homepage\":\"http://docs.wildfirechat.cn\",\"size\":8928,\"stargazers_count\":4694,\"watchers_count\":4694,\"language\":\"Java\",\"has_issues\":true,\"has_projects\":true,\"has_downloads\":true,\"has_wiki\":true,\"has_pages\":false,\"forks_count\":1040,\"mirror_url\":null,\"archived\":false,\"disabled\":false,\"open_issues_count\":14,\"license\":{\"key\":\"other\",\"name\":\"Other\",\"spdx_id\":\"NOASSERTION\",\"url\":null,\"node_id\":\"MDc6TGljZW5zZTA=\"},\"forks\":1040,\"open_issues\":14,\"watchers\":4694,\"default_branch\":\"wildfirechat\"},\"organization\":{\"login\":\"wildfirechat\",\"id\":33191460,\"node_id\":\"MDEyOk9yZ2FuaXphdGlvbjMzMTkxNDYw\",\"url\":\"https://api.github.com/orgs/wildfirechat\",\"repos_url\":\"https://api.github.com/orgs/wildfirechat/repos\",\"events_url\":\"https://api.github.com/orgs/wildfirechat/events\",\"hooks_url\":\"https://api.github.com/orgs/wildfirechat/hooks\",\"issues_url\":\"https://api.github.com/orgs/wildfirechat/issues\",\"members_url\":\"https://api.github.com/orgs/wildfirechat/members{/member}\",\"public_members_url\":\"https://api.github.com/orgs/wildfirechat/public_members{/member}\",\"avatar_url\":\"https://avatars0.githubusercontent.com/u/33191460?v=4\",\"description\":\"北京野火无限网络科技有限公司--专注于即时通讯技术,提供优质可控的即时通讯能力\"},\"sender\":{\"login\":\"yangwugui\",\"id\":9507380,\"node_id\":\"MDQ6VXNlcjk1MDczODA=\",\"avatar_url\":\"https://avatars3.githubusercontent.com/u/9507380?v=4\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/yangwugui\",\"html_url\":\"https://github.com/yangwugui\",\"followers_url\":\"https://api.github.com/users/yangwugui/followers\",\"following_url\":\"https://api.github.com/users/yangwugui/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/yangwugui/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/yangwugui/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/yangwugui/subscriptions\",\"organizations_url\":\"https://api.github.com/users/yangwugui/orgs\",\"repos_url\":\"https://api.github.com/users/yangwugui/repos\",\"events_url\":\"https://api.github.com/users/yangwugui/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/yangwugui/received_events\",\"type\":\"User\",\"site_admin\":false}}"; 15 | ForkEvent forkEvent = fromJson(event1); 16 | System.out.println(forkEvent.forkee.fork); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/github/pojo/Forkee.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.github.pojo; 2 | 3 | public class Forkee { 4 | public long id; 5 | public String node_id; 6 | public String name; 7 | public String full_name; 8 | public User owner; 9 | public String html_url; 10 | public String description; 11 | public boolean fork; 12 | public String url; 13 | public String forks_url; 14 | public String keys_url; 15 | public String collaborators_url; 16 | public String teams_url; 17 | public String hooks_url; 18 | public String issue_events_url; 19 | public String events_url; 20 | public String assignees_url; 21 | public String branches_url; 22 | public String tags_url; 23 | public String blobs_url; 24 | public String git_tags_url; 25 | public String git_refs_url; 26 | public String trees_url; 27 | public String statuses_url; 28 | public String languages_url; 29 | public String stargazers_url; 30 | public String contributors_url; 31 | public String subscribers_url; 32 | public String subscription_url; 33 | public String commits_url; 34 | public String git_commits_url; 35 | public String comments_url; 36 | public String issue_comment_url; 37 | public String contents_url; 38 | public String compare_url; 39 | public String merges_url; 40 | public String archive_url; 41 | public String downloads_url; 42 | public String issues_url; 43 | public String pulls_url; 44 | public String milestones_url; 45 | public String notifications_url; 46 | public String labels_url; 47 | public String releases_url; 48 | public String deployments_url; 49 | public String git_url; 50 | public String ssh_url; 51 | public String clone_url; 52 | public String svn_url; 53 | public String homepage; 54 | public int size; 55 | public int stargazers_count; 56 | public int watchers_count; 57 | public String language; 58 | public boolean has_issues; 59 | public boolean has_projects; 60 | public boolean has_downloads; 61 | public boolean has_wiki; 62 | public boolean has_pages; 63 | public int forks_count; 64 | public String mirror_url; 65 | public boolean archived; 66 | public boolean disabled; 67 | public int open_issues_count; 68 | public License license; 69 | public int forks; 70 | public int open_issues; 71 | public int watchers; 72 | public String default_branch; 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/github/pojo/Issue.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.github.pojo; 2 | 3 | import java.util.Date; 4 | 5 | public class Issue { 6 | public String url; 7 | public String repository_url; 8 | public String labels_url; 9 | public String comments_url; 10 | public String events_url; 11 | public String html_url; 12 | public String id; 13 | public String node_id; 14 | public String number; 15 | public String title; 16 | public User user; 17 | public String state; 18 | public boolean locked; 19 | public String assignee; 20 | public String[] assignees; 21 | public String milestone; 22 | public int comments; 23 | public Date created_at; 24 | public Date updated_at; 25 | public Date closed_at; 26 | public String author_association; 27 | public String body; 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/github/pojo/IssueCommentEvent.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.github.pojo; 2 | 3 | import com.google.gson.Gson; 4 | 5 | //https://developer.github.com/v3/activity/events/types/#issuecommentevent 6 | public class IssueCommentEvent { 7 | //The action that was performed on the comment. Can be one of created, edited, or deleted. 8 | public String action; 9 | public Issue issue; 10 | public Comment comment; 11 | public Repository repository; 12 | public User sender; 13 | 14 | public static IssueCommentEvent fromJson(String jsonStr) { 15 | IssueCommentEvent issueCommentEvent = new Gson().fromJson(jsonStr, IssueCommentEvent.class); 16 | return issueCommentEvent; 17 | } 18 | 19 | public static void main(String[] args) { 20 | String event1 = "{\"action\":\"created\",\"issue\":{\"url\":\"https://api.github.com/repos/wildfirechat/github_webhook/issues/1\",\"repository_url\":\"https://api.github.com/repos/wildfirechat/github_webhook\",\"labels_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/issues/1/labels{/name}\",\"comments_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/issues/1/comments\",\"events_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/issues/1/events\",\"html_url\":\"https://github.com/wildfirechat/github_webhook/issues/1\",\"id\":569491189,\"node_id\":\"MDU6SXNzdWU1Njk0OTExODk=\",\"number\":1,\"title\":\"test issue\",\"user\":{\"login\":\"heavyrain2012\",\"id\":34463389,\"node_id\":\"MDQ6VXNlcjM0NDYzMzg5\",\"avatar_url\":\"https://avatars0.githubusercontent.com/u/34463389?v=4\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/heavyrain2012\",\"html_url\":\"https://github.com/heavyrain2012\",\"followers_url\":\"https://api.github.com/users/heavyrain2012/followers\",\"following_url\":\"https://api.github.com/users/heavyrain2012/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/heavyrain2012/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/heavyrain2012/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/heavyrain2012/subscriptions\",\"organizations_url\":\"https://api.github.com/users/heavyrain2012/orgs\",\"repos_url\":\"https://api.github.com/users/heavyrain2012/repos\",\"events_url\":\"https://api.github.com/users/heavyrain2012/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/heavyrain2012/received_events\",\"type\":\"User\",\"site_admin\":false},\"labels\":[],\"state\":\"open\",\"locked\":false,\"assignee\":null,\"assignees\":[],\"milestone\":null,\"comments\":0,\"created_at\":\"2020-02-23T12:57:10Z\",\"updated_at\":\"2020-02-23T14:04:17Z\",\"closed_at\":null,\"author_association\":\"CONTRIBUTOR\",\"body\":\"this is a test issue\"},\"comment\":{\"url\":\"https://api.github.com/repos/wildfirechat/github_webhook/issues/comments/590072058\",\"html_url\":\"https://github.com/wildfirechat/github_webhook/issues/1#issuecomment-590072058\",\"issue_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/issues/1\",\"id\":590072058,\"node_id\":\"MDEyOklzc3VlQ29tbWVudDU5MDA3MjA1OA==\",\"user\":{\"login\":\"heavyrain2012\",\"id\":34463389,\"node_id\":\"MDQ6VXNlcjM0NDYzMzg5\",\"avatar_url\":\"https://avatars0.githubusercontent.com/u/34463389?v=4\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/heavyrain2012\",\"html_url\":\"https://github.com/heavyrain2012\",\"followers_url\":\"https://api.github.com/users/heavyrain2012/followers\",\"following_url\":\"https://api.github.com/users/heavyrain2012/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/heavyrain2012/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/heavyrain2012/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/heavyrain2012/subscriptions\",\"organizations_url\":\"https://api.github.com/users/heavyrain2012/orgs\",\"repos_url\":\"https://api.github.com/users/heavyrain2012/repos\",\"events_url\":\"https://api.github.com/users/heavyrain2012/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/heavyrain2012/received_events\",\"type\":\"User\",\"site_admin\":false},\"created_at\":\"2020-02-23T14:04:17Z\",\"updated_at\":\"2020-02-23T14:04:17Z\",\"author_association\":\"CONTRIBUTOR\",\"body\":\"tttt\"},\"repository\":{\"id\":242506330,\"node_id\":\"MDEwOlJlcG9zaXRvcnkyNDI1MDYzMzA=\",\"name\":\"github_webhook\",\"full_name\":\"wildfirechat/github_webhook\",\"private\":false,\"owner\":{\"login\":\"wildfirechat\",\"id\":33191460,\"node_id\":\"MDEyOk9yZ2FuaXphdGlvbjMzMTkxNDYw\",\"avatar_url\":\"https://avatars0.githubusercontent.com/u/33191460?v=4\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/wildfirechat\",\"html_url\":\"https://github.com/wildfirechat\",\"followers_url\":\"https://api.github.com/users/wildfirechat/followers\",\"following_url\":\"https://api.github.com/users/wildfirechat/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/wildfirechat/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/wildfirechat/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/wildfirechat/subscriptions\",\"organizations_url\":\"https://api.github.com/users/wildfirechat/orgs\",\"repos_url\":\"https://api.github.com/users/wildfirechat/repos\",\"events_url\":\"https://api.github.com/users/wildfirechat/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/wildfirechat/received_events\",\"type\":\"Organization\",\"site_admin\":false},\"html_url\":\"https://github.com/wildfirechat/github_webhook\",\"description\":\"Github webhook robot applaciton\",\"fork\":false,\"url\":\"https://api.github.com/repos/wildfirechat/github_webhook\",\"forks_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/forks\",\"keys_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/keys{/key_id}\",\"collaborators_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/collaborators{/collaborator}\",\"teams_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/teams\",\"hooks_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/hooks\",\"issue_events_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/issues/events{/number}\",\"events_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/events\",\"assignees_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/assignees{/user}\",\"branches_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/branches{/branch}\",\"tags_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/tags\",\"blobs_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/git/blobs{/sha}\",\"git_tags_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/git/tags{/sha}\",\"git_refs_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/git/refs{/sha}\",\"trees_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/git/trees{/sha}\",\"statuses_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/statuses/{sha}\",\"languages_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/languages\",\"stargazers_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/stargazers\",\"contributors_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/contributors\",\"subscribers_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/subscribers\",\"subscription_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/subscription\",\"commits_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/commits{/sha}\",\"git_commits_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/git/commits{/sha}\",\"comments_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/comments{/number}\",\"issue_comment_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/issues/comments{/number}\",\"contents_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/contents/{+path}\",\"compare_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/compare/{base}...{head}\",\"merges_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/merges\",\"archive_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/{archive_format}{/ref}\",\"downloads_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/downloads\",\"issues_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/issues{/number}\",\"pulls_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/pulls{/number}\",\"milestones_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/milestones{/number}\",\"notifications_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/notifications{?since,all,participating}\",\"labels_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/labels{/name}\",\"releases_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/releases{/id}\",\"deployments_url\":\"https://api.github.com/repos/wildfirechat/github_webhook/deployments\",\"created_at\":\"2020-02-23T11:41:25Z\",\"updated_at\":\"2020-02-23T13:58:24Z\",\"pushed_at\":\"2020-02-23T13:58:22Z\",\"git_url\":\"git://github.com/wildfirechat/github_webhook.git\",\"ssh_url\":\"git@github.com:wildfirechat/github_webhook.git\",\"clone_url\":\"https://github.com/wildfirechat/github_webhook.git\",\"svn_url\":\"https://github.com/wildfirechat/github_webhook\",\"homepage\":null,\"size\":797,\"stargazers_count\":0,\"watchers_count\":0,\"language\":\"Java\",\"has_issues\":true,\"has_projects\":true,\"has_downloads\":true,\"has_wiki\":true,\"has_pages\":false,\"forks_count\":0,\"mirror_url\":null,\"archived\":false,\"disabled\":false,\"open_issues_count\":1,\"license\":{\"key\":\"other\",\"name\":\"Other\",\"spdx_id\":\"NOASSERTION\",\"url\":null,\"node_id\":\"MDc6TGljZW5zZTA=\"},\"forks\":0,\"open_issues\":1,\"watchers\":0,\"default_branch\":\"master\"},\"organization\":{\"login\":\"wildfirechat\",\"id\":33191460,\"node_id\":\"MDEyOk9yZ2FuaXphdGlvbjMzMTkxNDYw\",\"url\":\"https://api.github.com/orgs/wildfirechat\",\"repos_url\":\"https://api.github.com/orgs/wildfirechat/repos\",\"events_url\":\"https://api.github.com/orgs/wildfirechat/events\",\"hooks_url\":\"https://api.github.com/orgs/wildfirechat/hooks\",\"issues_url\":\"https://api.github.com/orgs/wildfirechat/issues\",\"members_url\":\"https://api.github.com/orgs/wildfirechat/members{/member}\",\"public_members_url\":\"https://api.github.com/orgs/wildfirechat/public_members{/member}\",\"avatar_url\":\"https://avatars0.githubusercontent.com/u/33191460?v=4\",\"description\":\"北京野火无限网络科技有限公司--专注于即时通讯技术,提供优质可控的即时通讯能力\"},\"sender\":{\"login\":\"heavyrain2012\",\"id\":34463389,\"node_id\":\"MDQ6VXNlcjM0NDYzMzg5\",\"avatar_url\":\"https://avatars0.githubusercontent.com/u/34463389?v=4\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/heavyrain2012\",\"html_url\":\"https://github.com/heavyrain2012\",\"followers_url\":\"https://api.github.com/users/heavyrain2012/followers\",\"following_url\":\"https://api.github.com/users/heavyrain2012/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/heavyrain2012/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/heavyrain2012/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/heavyrain2012/subscriptions\",\"organizations_url\":\"https://api.github.com/users/heavyrain2012/orgs\",\"repos_url\":\"https://api.github.com/users/heavyrain2012/repos\",\"events_url\":\"https://api.github.com/users/heavyrain2012/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/heavyrain2012/received_events\",\"type\":\"User\",\"site_admin\":false}}"; 21 | IssueCommentEvent issueCommentEvent = fromJson(event1); 22 | System.out.println(issueCommentEvent.action); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/github/pojo/IssueEvent.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.github.pojo; 2 | 3 | import com.google.gson.Gson; 4 | 5 | //https://developer.github.com/v3/activity/events/types/#issuesevent 6 | public class IssueEvent { 7 | //The action that was performed. Can be one of opened, edited, deleted, pinned, unpinned, closed, reopened, assigned, unassigned, labeled, unlabeled, locked, unlocked, transferred, milestoned, or demilestoned. 8 | public String action; 9 | public Issue issue; 10 | public Repository repository; 11 | public Sender sender; 12 | 13 | public static IssueEvent fromJson(String jsonStr) { 14 | return new Gson().fromJson(jsonStr, IssueEvent.class); 15 | } 16 | 17 | public static void main(String[] args) { 18 | String event1 = "{\"action\":\"closed\",\"issue\":{\"url\":\"https://api.github.com/repos/wildfirechat/server/issues/257\",\"repository_url\":\"https://api.github.com/repos/wildfirechat/server\",\"labels_url\":\"https://api.github.com/repos/wildfirechat/server/issues/257/labels{/name}\",\"comments_url\":\"https://api.github.com/repos/wildfirechat/server/issues/257/comments\",\"events_url\":\"https://api.github.com/repos/wildfirechat/server/issues/257/events\",\"html_url\":\"https://github.com/wildfirechat/server/issues/257\",\"id\":681562734,\"node_id\":\"MDU6SXNzdWU2ODE1NjI3MzQ=\",\"number\":257,\"title\":\"建议:用户在线状态回调希望回调所在包名称或当前登录的包唯一标识\",\"user\":{\"login\":\"zuoliang0\",\"id\":8434253,\"node_id\":\"MDQ6VXNlcjg0MzQyNTM=\",\"avatar_url\":\"https://avatars1.githubusercontent.com/u/8434253?v=4\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/zuoliang0\",\"html_url\":\"https://github.com/zuoliang0\",\"followers_url\":\"https://api.github.com/users/zuoliang0/followers\",\"following_url\":\"https://api.github.com/users/zuoliang0/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/zuoliang0/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/zuoliang0/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/zuoliang0/subscriptions\",\"organizations_url\":\"https://api.github.com/users/zuoliang0/orgs\",\"repos_url\":\"https://api.github.com/users/zuoliang0/repos\",\"events_url\":\"https://api.github.com/users/zuoliang0/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/zuoliang0/received_events\",\"type\":\"User\",\"site_admin\":false},\"labels\":[{\"id\":1205138170,\"node_id\":\"MDU6TGFiZWwxMjA1MTM4MTcw\",\"url\":\"https://api.github.com/repos/wildfirechat/server/labels/enhancement\",\"name\":\"enhancement\",\"color\":\"a2eeef\",\"default\":true,\"description\":\"New feature or request\"}],\"state\":\"closed\",\"locked\":false,\"assignee\":null,\"assignees\":[],\"milestone\":null,\"comments\":14,\"created_at\":\"2020-08-19T05:41:55Z\",\"updated_at\":\"2020-08-27T05:26:57Z\",\"closed_at\":\"2020-08-27T05:26:57Z\",\"author_association\":\"NONE\",\"active_lock_reason\":null,\"body\":\"回调在线状态这个需求也是我提出的,我们现在使用的是融云服务,计划在年底迁移到野火,目前正在做前期对接,后台对接时发现回调状态不包含当前所登录的包信息,希望能拿到这些信息。我们有多个app,用户可以在多个app之间登录。\",\"performed_via_github_app\":null},\"repository\":{\"id\":167204613,\"node_id\":\"MDEwOlJlcG9zaXRvcnkxNjcyMDQ2MTM=\",\"name\":\"server\",\"full_name\":\"wildfirechat/server\",\"private\":false,\"owner\":{\"login\":\"wildfirechat\",\"id\":33191460,\"node_id\":\"MDEyOk9yZ2FuaXphdGlvbjMzMTkxNDYw\",\"avatar_url\":\"https://avatars0.githubusercontent.com/u/33191460?v=4\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/wildfirechat\",\"html_url\":\"https://github.com/wildfirechat\",\"followers_url\":\"https://api.github.com/users/wildfirechat/followers\",\"following_url\":\"https://api.github.com/users/wildfirechat/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/wildfirechat/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/wildfirechat/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/wildfirechat/subscriptions\",\"organizations_url\":\"https://api.github.com/users/wildfirechat/orgs\",\"repos_url\":\"https://api.github.com/users/wildfirechat/repos\",\"events_url\":\"https://api.github.com/users/wildfirechat/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/wildfirechat/received_events\",\"type\":\"Organization\",\"site_admin\":false},\"html_url\":\"https://github.com/wildfirechat/server\",\"description\":\"即时通讯(IM)系统\",\"fork\":false,\"url\":\"https://api.github.com/repos/wildfirechat/server\",\"forks_url\":\"https://api.github.com/repos/wildfirechat/server/forks\",\"keys_url\":\"https://api.github.com/repos/wildfirechat/server/keys{/key_id}\",\"collaborators_url\":\"https://api.github.com/repos/wildfirechat/server/collaborators{/collaborator}\",\"teams_url\":\"https://api.github.com/repos/wildfirechat/server/teams\",\"hooks_url\":\"https://api.github.com/repos/wildfirechat/server/hooks\",\"issue_events_url\":\"https://api.github.com/repos/wildfirechat/server/issues/events{/number}\",\"events_url\":\"https://api.github.com/repos/wildfirechat/server/events\",\"assignees_url\":\"https://api.github.com/repos/wildfirechat/server/assignees{/user}\",\"branches_url\":\"https://api.github.com/repos/wildfirechat/server/branches{/branch}\",\"tags_url\":\"https://api.github.com/repos/wildfirechat/server/tags\",\"blobs_url\":\"https://api.github.com/repos/wildfirechat/server/git/blobs{/sha}\",\"git_tags_url\":\"https://api.github.com/repos/wildfirechat/server/git/tags{/sha}\",\"git_refs_url\":\"https://api.github.com/repos/wildfirechat/server/git/refs{/sha}\",\"trees_url\":\"https://api.github.com/repos/wildfirechat/server/git/trees{/sha}\",\"statuses_url\":\"https://api.github.com/repos/wildfirechat/server/statuses/{sha}\",\"languages_url\":\"https://api.github.com/repos/wildfirechat/server/languages\",\"stargazers_url\":\"https://api.github.com/repos/wildfirechat/server/stargazers\",\"contributors_url\":\"https://api.github.com/repos/wildfirechat/server/contributors\",\"subscribers_url\":\"https://api.github.com/repos/wildfirechat/server/subscribers\",\"subscription_url\":\"https://api.github.com/repos/wildfirechat/server/subscription\",\"commits_url\":\"https://api.github.com/repos/wildfirechat/server/commits{/sha}\",\"git_commits_url\":\"https://api.github.com/repos/wildfirechat/server/git/commits{/sha}\",\"comments_url\":\"https://api.github.com/repos/wildfirechat/server/comments{/number}\",\"issue_comment_url\":\"https://api.github.com/repos/wildfirechat/server/issues/comments{/number}\",\"contents_url\":\"https://api.github.com/repos/wildfirechat/server/contents/{+path}\",\"compare_url\":\"https://api.github.com/repos/wildfirechat/server/compare/{base}...{head}\",\"merges_url\":\"https://api.github.com/repos/wildfirechat/server/merges\",\"archive_url\":\"https://api.github.com/repos/wildfirechat/server/{archive_format}{/ref}\",\"downloads_url\":\"https://api.github.com/repos/wildfirechat/server/downloads\",\"issues_url\":\"https://api.github.com/repos/wildfirechat/server/issues{/number}\",\"pulls_url\":\"https://api.github.com/repos/wildfirechat/server/pulls{/number}\",\"milestones_url\":\"https://api.github.com/repos/wildfirechat/server/milestones{/number}\",\"notifications_url\":\"https://api.github.com/repos/wildfirechat/server/notifications{?since,all,participating}\",\"labels_url\":\"https://api.github.com/repos/wildfirechat/server/labels{/name}\",\"releases_url\":\"https://api.github.com/repos/wildfirechat/server/releases{/id}\",\"deployments_url\":\"https://api.github.com/repos/wildfirechat/server/deployments\",\"created_at\":\"2019-01-23T15:21:28Z\",\"updated_at\":\"2020-08-26T12:17:45Z\",\"pushed_at\":\"2020-08-25T13:04:59Z\",\"git_url\":\"git://github.com/wildfirechat/server.git\",\"ssh_url\":\"git@github.com:wildfirechat/server.git\",\"clone_url\":\"https://github.com/wildfirechat/server.git\",\"svn_url\":\"https://github.com/wildfirechat/server\",\"homepage\":\"http://docs.wildfirechat.cn\",\"size\":9350,\"stargazers_count\":5330,\"watchers_count\":5330,\"language\":\"Java\",\"has_issues\":true,\"has_projects\":true,\"has_downloads\":true,\"has_wiki\":true,\"has_pages\":false,\"forks_count\":1204,\"mirror_url\":null,\"archived\":false,\"disabled\":false,\"open_issues_count\":9,\"license\":{\"key\":\"other\",\"name\":\"Other\",\"spdx_id\":\"NOASSERTION\",\"url\":null,\"node_id\":\"MDc6TGljZW5zZTA=\"},\"forks\":1204,\"open_issues\":9,\"watchers\":5330,\"default_branch\":\"wildfirechat\"},\"organization\":{\"login\":\"wildfirechat\",\"id\":33191460,\"node_id\":\"MDEyOk9yZ2FuaXphdGlvbjMzMTkxNDYw\",\"url\":\"https://api.github.com/orgs/wildfirechat\",\"repos_url\":\"https://api.github.com/orgs/wildfirechat/repos\",\"events_url\":\"https://api.github.com/orgs/wildfirechat/events\",\"hooks_url\":\"https://api.github.com/orgs/wildfirechat/hooks\",\"issues_url\":\"https://api.github.com/orgs/wildfirechat/issues\",\"members_url\":\"https://api.github.com/orgs/wildfirechat/members{/member}\",\"public_members_url\":\"https://api.github.com/orgs/wildfirechat/public_members{/member}\",\"avatar_url\":\"https://avatars0.githubusercontent.com/u/33191460?v=4\",\"description\":\"北京野火无限网络科技有限公司--专注于即时通讯技术,提供优质可控的即时通讯能力\"},\"sender\":{\"login\":\"heavyrain2012\",\"id\":34463389,\"node_id\":\"MDQ6VXNlcjM0NDYzMzg5\",\"avatar_url\":\"https://avatars0.githubusercontent.com/u/34463389?v=4\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/heavyrain2012\",\"html_url\":\"https://github.com/heavyrain2012\",\"followers_url\":\"https://api.github.com/users/heavyrain2012/followers\",\"following_url\":\"https://api.github.com/users/heavyrain2012/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/heavyrain2012/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/heavyrain2012/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/heavyrain2012/subscriptions\",\"organizations_url\":\"https://api.github.com/users/heavyrain2012/orgs\",\"repos_url\":\"https://api.github.com/users/heavyrain2012/repos\",\"events_url\":\"https://api.github.com/users/heavyrain2012/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/heavyrain2012/received_events\",\"type\":\"User\",\"site_admin\":false}}"; 19 | IssueEvent openedIssue = new Gson().fromJson(event1, IssueEvent.class); 20 | System.out.println(openedIssue.action); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/github/pojo/License.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.github.pojo; 2 | 3 | public class License { 4 | public String key; 5 | public String name; 6 | public String spdx_id; 7 | public String url; 8 | public String node_id; 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/github/pojo/PingEvent.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.github.pojo; 2 | 3 | import com.google.gson.Gson; 4 | 5 | //https://developer.github.com/v3/activity/events/types/#watchevent 6 | public class PingEvent { 7 | //The action that was performed. Currently, can only be started. 8 | public Repository repository; 9 | public User sender; 10 | 11 | public static PingEvent fromJson(String jsonStr) { 12 | return new Gson().fromJson(jsonStr, PingEvent.class); 13 | } 14 | 15 | public static void main(String[] args) { 16 | String event = "{\"zen\":\"Mind your words, they are important.\",\"hook_id\":245889670,\"hook\":{\"type\":\"Repository\",\"id\":245889670,\"name\":\"web\",\"active\":true,\"events\":[\"push\"],\"config\":{\"content_type\":\"json\",\"insecure_ssl\":\"0\",\"url\":\"http://wildfirechat.cn:8890/github/payload\"},\"updated_at\":\"2020-09-02T08:01:11Z\",\"created_at\":\"2020-09-02T08:01:11Z\",\"url\":\"https://api.github.com/repos/heavyrain2012/account_book/hooks/245889670\",\"test_url\":\"https://api.github.com/repos/heavyrain2012/account_book/hooks/245889670/test\",\"ping_url\":\"https://api.github.com/repos/heavyrain2012/account_book/hooks/245889670/pings\",\"last_response\":{\"code\":null,\"status\":\"unused\",\"message\":null}},\"repository\":{\"id\":196691777,\"node_id\":\"MDEwOlJlcG9zaXRvcnkxOTY2OTE3Nzc=\",\"name\":\"account_book\",\"full_name\":\"heavyrain2012/account_book\",\"private\":true,\"owner\":{\"login\":\"heavyrain2012\",\"id\":34463389,\"node_id\":\"MDQ6VXNlcjM0NDYzMzg5\",\"avatar_url\":\"https://avatars0.githubusercontent.com/u/34463389?v=4\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/heavyrain2012\",\"html_url\":\"https://github.com/heavyrain2012\",\"followers_url\":\"https://api.github.com/users/heavyrain2012/followers\",\"following_url\":\"https://api.github.com/users/heavyrain2012/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/heavyrain2012/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/heavyrain2012/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/heavyrain2012/subscriptions\",\"organizations_url\":\"https://api.github.com/users/heavyrain2012/orgs\",\"repos_url\":\"https://api.github.com/users/heavyrain2012/repos\",\"events_url\":\"https://api.github.com/users/heavyrain2012/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/heavyrain2012/received_events\",\"type\":\"User\",\"site_admin\":false},\"html_url\":\"https://github.com/heavyrain2012/account_book\",\"description\":null,\"fork\":false,\"url\":\"https://api.github.com/repos/heavyrain2012/account_book\",\"forks_url\":\"https://api.github.com/repos/heavyrain2012/account_book/forks\",\"keys_url\":\"https://api.github.com/repos/heavyrain2012/account_book/keys{/key_id}\",\"collaborators_url\":\"https://api.github.com/repos/heavyrain2012/account_book/collaborators{/collaborator}\",\"teams_url\":\"https://api.github.com/repos/heavyrain2012/account_book/teams\",\"hooks_url\":\"https://api.github.com/repos/heavyrain2012/account_book/hooks\",\"issue_events_url\":\"https://api.github.com/repos/heavyrain2012/account_book/issues/events{/number}\",\"events_url\":\"https://api.github.com/repos/heavyrain2012/account_book/events\",\"assignees_url\":\"https://api.github.com/repos/heavyrain2012/account_book/assignees{/user}\",\"branches_url\":\"https://api.github.com/repos/heavyrain2012/account_book/branches{/branch}\",\"tags_url\":\"https://api.github.com/repos/heavyrain2012/account_book/tags\",\"blobs_url\":\"https://api.github.com/repos/heavyrain2012/account_book/git/blobs{/sha}\",\"git_tags_url\":\"https://api.github.com/repos/heavyrain2012/account_book/git/tags{/sha}\",\"git_refs_url\":\"https://api.github.com/repos/heavyrain2012/account_book/git/refs{/sha}\",\"trees_url\":\"https://api.github.com/repos/heavyrain2012/account_book/git/trees{/sha}\",\"statuses_url\":\"https://api.github.com/repos/heavyrain2012/account_book/statuses/{sha}\",\"languages_url\":\"https://api.github.com/repos/heavyrain2012/account_book/languages\",\"stargazers_url\":\"https://api.github.com/repos/heavyrain2012/account_book/stargazers\",\"contributors_url\":\"https://api.github.com/repos/heavyrain2012/account_book/contributors\",\"subscribers_url\":\"https://api.github.com/repos/heavyrain2012/account_book/subscribers\",\"subscription_url\":\"https://api.github.com/repos/heavyrain2012/account_book/subscription\",\"commits_url\":\"https://api.github.com/repos/heavyrain2012/account_book/commits{/sha}\",\"git_commits_url\":\"https://api.github.com/repos/heavyrain2012/account_book/git/commits{/sha}\",\"comments_url\":\"https://api.github.com/repos/heavyrain2012/account_book/comments{/number}\",\"issue_comment_url\":\"https://api.github.com/repos/heavyrain2012/account_book/issues/comments{/number}\",\"contents_url\":\"https://api.github.com/repos/heavyrain2012/account_book/contents/{+path}\",\"compare_url\":\"https://api.github.com/repos/heavyrain2012/account_book/compare/{base}...{head}\",\"merges_url\":\"https://api.github.com/repos/heavyrain2012/account_book/merges\",\"archive_url\":\"https://api.github.com/repos/heavyrain2012/account_book/{archive_format}{/ref}\",\"downloads_url\":\"https://api.github.com/repos/heavyrain2012/account_book/downloads\",\"issues_url\":\"https://api.github.com/repos/heavyrain2012/account_book/issues{/number}\",\"pulls_url\":\"https://api.github.com/repos/heavyrain2012/account_book/pulls{/number}\",\"milestones_url\":\"https://api.github.com/repos/heavyrain2012/account_book/milestones{/number}\",\"notifications_url\":\"https://api.github.com/repos/heavyrain2012/account_book/notifications{?since,all,participating}\",\"labels_url\":\"https://api.github.com/repos/heavyrain2012/account_book/labels{/name}\",\"releases_url\":\"https://api.github.com/repos/heavyrain2012/account_book/releases{/id}\",\"deployments_url\":\"https://api.github.com/repos/heavyrain2012/account_book/deployments\",\"created_at\":\"2019-07-13T07:23:26Z\",\"updated_at\":\"2020-09-02T07:56:00Z\",\"pushed_at\":\"2020-09-02T07:55:58Z\",\"git_url\":\"git://github.com/heavyrain2012/account_book.git\",\"ssh_url\":\"git@github.com:heavyrain2012/account_book.git\",\"clone_url\":\"https://github.com/heavyrain2012/account_book.git\",\"svn_url\":\"https://github.com/heavyrain2012/account_book\",\"homepage\":null,\"size\":84,\"stargazers_count\":0,\"watchers_count\":0,\"language\":null,\"has_issues\":true,\"has_projects\":true,\"has_downloads\":true,\"has_wiki\":true,\"has_pages\":false,\"forks_count\":0,\"mirror_url\":null,\"archived\":false,\"disabled\":false,\"open_issues_count\":0,\"license\":null,\"forks\":0,\"open_issues\":0,\"watchers\":0,\"default_branch\":\"master\"},\"sender\":{\"login\":\"heavyrain2012\",\"id\":34463389,\"node_id\":\"MDQ6VXNlcjM0NDYzMzg5\",\"avatar_url\":\"https://avatars0.githubusercontent.com/u/34463389?v=4\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/heavyrain2012\",\"html_url\":\"https://github.com/heavyrain2012\",\"followers_url\":\"https://api.github.com/users/heavyrain2012/followers\",\"following_url\":\"https://api.github.com/users/heavyrain2012/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/heavyrain2012/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/heavyrain2012/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/heavyrain2012/subscriptions\",\"organizations_url\":\"https://api.github.com/users/heavyrain2012/orgs\",\"repos_url\":\"https://api.github.com/users/heavyrain2012/repos\",\"events_url\":\"https://api.github.com/users/heavyrain2012/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/heavyrain2012/received_events\",\"type\":\"User\",\"site_admin\":false}}"; 17 | PingEvent watchEvent = fromJson(event); 18 | System.out.println(""); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/github/pojo/PullRequest.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.github.pojo; 2 | 3 | import java.util.Date; 4 | 5 | public class PullRequest { 6 | public String html_url; 7 | public String id; 8 | public String node_id; 9 | public String number; 10 | public String title; 11 | public String body; 12 | public User user; 13 | public String state; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/github/pojo/PushEvent.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.github.pojo; 2 | 3 | import com.google.gson.Gson; 4 | 5 | public class PushEvent { 6 | public String ref; 7 | public String before; 8 | public String after; 9 | public boolean created; 10 | public boolean deleted; 11 | public boolean forced; 12 | public String base_ref; 13 | public String compare; 14 | public Commit[] commits; 15 | public Commit head_commit; 16 | public Repository repository; 17 | public Pusher pusher; 18 | public Sender sender; 19 | 20 | public static PushEvent fromJson(String jsonStr) { 21 | return new Gson().fromJson(jsonStr, PushEvent.class); 22 | } 23 | 24 | public static void main(String[] args) { 25 | String event1 = "{\"ref\":\"refs/heads/master\",\"before\":\"0000000000000000000000000000000000000000\",\"after\":\"d7c02e15ef0f3eca28400bc92f2decbd6b9df2e0\",\"repository\":{\"id\":242506330,\"node_id\":\"MDEwOlJlcG9zaXRvcnkyNDI1MDYzMzA=\",\"name\":\"github_webhoot\",\"full_name\":\"wildfirechat/github_webhoot\",\"private\":false,\"owner\":{\"name\":\"wildfirechat\",\"email\":\"heavyrain.lee@wildfirechat.cn\",\"login\":\"wildfirechat\",\"id\":33191460,\"node_id\":\"MDEyOk9yZ2FuaXphdGlvbjMzMTkxNDYw\",\"avatar_url\":\"https://avatars0.githubusercontent.com/u/33191460?v=4\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/wildfirechat\",\"html_url\":\"https://github.com/wildfirechat\",\"followers_url\":\"https://api.github.com/users/wildfirechat/followers\",\"following_url\":\"https://api.github.com/users/wildfirechat/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/wildfirechat/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/wildfirechat/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/wildfirechat/subscriptions\",\"organizations_url\":\"https://api.github.com/users/wildfirechat/orgs\",\"repos_url\":\"https://api.github.com/users/wildfirechat/repos\",\"events_url\":\"https://api.github.com/users/wildfirechat/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/wildfirechat/received_events\",\"type\":\"Organization\",\"site_admin\":false},\"html_url\":\"https://github.com/wildfirechat/github_webhoot\",\"description\":\"Github webhook robot applaciton\",\"fork\":false,\"url\":\"https://github.com/wildfirechat/github_webhoot\",\"forks_url\":\"https://api.github.com/repos/wildfirechat/github_webhoot/forks\",\"keys_url\":\"https://api.github.com/repos/wildfirechat/github_webhoot/keys{/key_id}\",\"collaborators_url\":\"https://api.github.com/repos/wildfirechat/github_webhoot/collaborators{/collaborator}\",\"teams_url\":\"https://api.github.com/repos/wildfirechat/github_webhoot/teams\",\"hooks_url\":\"https://api.github.com/repos/wildfirechat/github_webhoot/hooks\",\"issue_events_url\":\"https://api.github.com/repos/wildfirechat/github_webhoot/issues/events{/number}\",\"events_url\":\"https://api.github.com/repos/wildfirechat/github_webhoot/events\",\"assignees_url\":\"https://api.github.com/repos/wildfirechat/github_webhoot/assignees{/user}\",\"branches_url\":\"https://api.github.com/repos/wildfirechat/github_webhoot/branches{/branch}\",\"tags_url\":\"https://api.github.com/repos/wildfirechat/github_webhoot/tags\",\"blobs_url\":\"https://api.github.com/repos/wildfirechat/github_webhoot/git/blobs{/sha}\",\"git_tags_url\":\"https://api.github.com/repos/wildfirechat/github_webhoot/git/tags{/sha}\",\"git_refs_url\":\"https://api.github.com/repos/wildfirechat/github_webhoot/git/refs{/sha}\",\"trees_url\":\"https://api.github.com/repos/wildfirechat/github_webhoot/git/trees{/sha}\",\"statuses_url\":\"https://api.github.com/repos/wildfirechat/github_webhoot/statuses/{sha}\",\"languages_url\":\"https://api.github.com/repos/wildfirechat/github_webhoot/languages\",\"stargazers_url\":\"https://api.github.com/repos/wildfirechat/github_webhoot/stargazers\",\"contributors_url\":\"https://api.github.com/repos/wildfirechat/github_webhoot/contributors\",\"subscribers_url\":\"https://api.github.com/repos/wildfirechat/github_webhoot/subscribers\",\"subscription_url\":\"https://api.github.com/repos/wildfirechat/github_webhoot/subscription\",\"commits_url\":\"https://api.github.com/repos/wildfirechat/github_webhoot/commits{/sha}\",\"git_commits_url\":\"https://api.github.com/repos/wildfirechat/github_webhoot/git/commits{/sha}\",\"comments_url\":\"https://api.github.com/repos/wildfirechat/github_webhoot/comments{/number}\",\"issue_comment_url\":\"https://api.github.com/repos/wildfirechat/github_webhoot/issues/comments{/number}\",\"contents_url\":\"https://api.github.com/repos/wildfirechat/github_webhoot/contents/{+path}\",\"compare_url\":\"https://api.github.com/repos/wildfirechat/github_webhoot/compare/{base}...{head}\",\"merges_url\":\"https://api.github.com/repos/wildfirechat/github_webhoot/merges\",\"archive_url\":\"https://api.github.com/repos/wildfirechat/github_webhoot/{archive_format}{/ref}\",\"downloads_url\":\"https://api.github.com/repos/wildfirechat/github_webhoot/downloads\",\"issues_url\":\"https://api.github.com/repos/wildfirechat/github_webhoot/issues{/number}\",\"pulls_url\":\"https://api.github.com/repos/wildfirechat/github_webhoot/pulls{/number}\",\"milestones_url\":\"https://api.github.com/repos/wildfirechat/github_webhoot/milestones{/number}\",\"notifications_url\":\"https://api.github.com/repos/wildfirechat/github_webhoot/notifications{?since,all,participating}\",\"labels_url\":\"https://api.github.com/repos/wildfirechat/github_webhoot/labels{/name}\",\"releases_url\":\"https://api.github.com/repos/wildfirechat/github_webhoot/releases{/id}\",\"deployments_url\":\"https://api.github.com/repos/wildfirechat/github_webhoot/deployments\",\"created_at\":1582458085,\"updated_at\":\"2020-02-23T11:41:25Z\",\"pushed_at\":1582458469,\"git_url\":\"git://github.com/wildfirechat/github_webhoot.git\",\"ssh_url\":\"git@github.com:wildfirechat/github_webhoot.git\",\"clone_url\":\"https://github.com/wildfirechat/github_webhoot.git\",\"svn_url\":\"https://github.com/wildfirechat/github_webhoot\",\"homepage\":null,\"size\":0,\"stargazers_count\":0,\"watchers_count\":0,\"language\":null,\"has_issues\":true,\"has_projects\":true,\"has_downloads\":true,\"has_wiki\":true,\"has_pages\":false,\"forks_count\":0,\"mirror_url\":null,\"archived\":false,\"disabled\":false,\"open_issues_count\":0,\"license\":null,\"forks\":0,\"open_issues\":0,\"watchers\":0,\"default_branch\":\"master\",\"stargazers\":0,\"master_branch\":\"master\",\"organization\":\"wildfirechat\"},\"pusher\":{\"name\":\"heavyrain2012\",\"email\":\"heavyrain.lee@gmail.com\"},\"organization\":{\"login\":\"wildfirechat\",\"id\":33191460,\"node_id\":\"MDEyOk9yZ2FuaXphdGlvbjMzMTkxNDYw\",\"url\":\"https://api.github.com/orgs/wildfirechat\",\"repos_url\":\"https://api.github.com/orgs/wildfirechat/repos\",\"events_url\":\"https://api.github.com/orgs/wildfirechat/events\",\"hooks_url\":\"https://api.github.com/orgs/wildfirechat/hooks\",\"issues_url\":\"https://api.github.com/orgs/wildfirechat/issues\",\"members_url\":\"https://api.github.com/orgs/wildfirechat/members{/member}\",\"public_members_url\":\"https://api.github.com/orgs/wildfirechat/public_members{/member}\",\"avatar_url\":\"https://avatars0.githubusercontent.com/u/33191460?v=4\",\"description\":\"北京野火无限网络科技有限公司--专注于即时通讯技术,提供优质可控的即时通讯能力\"},\"sender\":{\"login\":\"heavyrain2012\",\"id\":34463389,\"node_id\":\"MDQ6VXNlcjM0NDYzMzg5\",\"avatar_url\":\"https://avatars0.githubusercontent.com/u/34463389?v=4\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/heavyrain2012\",\"html_url\":\"https://github.com/heavyrain2012\",\"followers_url\":\"https://api.github.com/users/heavyrain2012/followers\",\"following_url\":\"https://api.github.com/users/heavyrain2012/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/heavyrain2012/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/heavyrain2012/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/heavyrain2012/subscriptions\",\"organizations_url\":\"https://api.github.com/users/heavyrain2012/orgs\",\"repos_url\":\"https://api.github.com/users/heavyrain2012/repos\",\"events_url\":\"https://api.github.com/users/heavyrain2012/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/heavyrain2012/received_events\",\"type\":\"User\",\"site_admin\":false},\"created\":true,\"deleted\":false,\"forced\":false,\"base_ref\":null,\"compare\":\"https://github.com/wildfirechat/github_webhoot/commit/d7c02e15ef0f\",\"commits\":[{\"id\":\"d7c02e15ef0f3eca28400bc92f2decbd6b9df2e0\",\"tree_id\":\"7311f1117ef41ec7585ae1e8ade79c1dae72ae7f\",\"distinct\":true,\"message\":\"first commit\",\"timestamp\":\"2020-02-23T19:47:09+08:00\",\"url\":\"https://github.com/wildfirechat/github_webhoot/commit/d7c02e15ef0f3eca28400bc92f2decbd6b9df2e0\",\"author\":{\"name\":\"heavyrain2012\",\"email\":\"heavyrain.lee@gmail.com\",\"username\":\"heavyrain2012\"},\"committer\":{\"name\":\"heavyrain2012\",\"email\":\"heavyrain.lee@gmail.com\",\"username\":\"heavyrain2012\"},\"added\":[\".gitignore\",\"LICENSE\",\"README.md\",\"github_webhook.iml\",\"mvnw\",\"mvnw.cmd\",\"pom.xml\",\"src/lib/common-0.21.jar\",\"src/lib/sdk-0.21.jar\",\"src/main/java/cn/wildfirechat/app/Application.java\",\"src/main/java/cn/wildfirechat/app/Controller.java\",\"src/main/java/cn/wildfirechat/app/HttpUtils.java\",\"src/main/java/cn/wildfirechat/app/Record.java\",\"src/main/java/cn/wildfirechat/app/RestResult.java\",\"src/main/java/cn/wildfirechat/app/Service.java\",\"src/main/java/cn/wildfirechat/app/ServiceImpl.java\",\"src/main/java/cn/wildfirechat/app/TulingResponse.java\",\"src/main/java/cn/wildfirechat/app/Utils.java\",\"src/main/java/cn/wildfirechat/app/pojo/License.java\",\"src/main/java/cn/wildfirechat/app/pojo/Owner.java\",\"src/main/java/cn/wildfirechat/app/pojo/Repository.java\",\"src/main/java/cn/wildfirechat/app/pojo/Sender.java\",\"src/main/java/cn/wildfirechat/app/pojo/StarEvent.java\",\"src/main/java/ikidou/reflect/TypeBuilder.java\",\"src/main/java/ikidou/reflect/TypeToken.java\",\"src/main/java/ikidou/reflect/exception/TypeException.java\",\"src/main/java/ikidou/reflect/typeimpl/ParameterizedTypeImpl.java\",\"src/main/java/ikidou/reflect/typeimpl/WildcardTypeImpl.java\",\"src/main/resources/application.properties\",\"src/test/java/cn/wildfirechat/app/ApplicationTests.java\"],\"removed\":[],\"modified\":[]}],\"head_commit\":{\"id\":\"d7c02e15ef0f3eca28400bc92f2decbd6b9df2e0\",\"tree_id\":\"7311f1117ef41ec7585ae1e8ade79c1dae72ae7f\",\"distinct\":true,\"message\":\"first commit\",\"timestamp\":\"2020-02-23T19:47:09+08:00\",\"url\":\"https://github.com/wildfirechat/github_webhoot/commit/d7c02e15ef0f3eca28400bc92f2decbd6b9df2e0\",\"author\":{\"name\":\"heavyrain2012\",\"email\":\"heavyrain.lee@gmail.com\",\"username\":\"heavyrain2012\"},\"committer\":{\"name\":\"heavyrain2012\",\"email\":\"heavyrain.lee@gmail.com\",\"username\":\"heavyrain2012\"},\"added\":[\".gitignore\",\"LICENSE\",\"README.md\",\"github_webhook.iml\",\"mvnw\",\"mvnw.cmd\",\"pom.xml\",\"src/lib/common-0.21.jar\",\"src/lib/sdk-0.21.jar\",\"src/main/java/cn/wildfirechat/app/Application.java\",\"src/main/java/cn/wildfirechat/app/Controller.java\",\"src/main/java/cn/wildfirechat/app/HttpUtils.java\",\"src/main/java/cn/wildfirechat/app/Record.java\",\"src/main/java/cn/wildfirechat/app/RestResult.java\",\"src/main/java/cn/wildfirechat/app/Service.java\",\"src/main/java/cn/wildfirechat/app/ServiceImpl.java\",\"src/main/java/cn/wildfirechat/app/TulingResponse.java\",\"src/main/java/cn/wildfirechat/app/Utils.java\",\"src/main/java/cn/wildfirechat/app/pojo/License.java\",\"src/main/java/cn/wildfirechat/app/pojo/Owner.java\",\"src/main/java/cn/wildfirechat/app/pojo/Repository.java\",\"src/main/java/cn/wildfirechat/app/pojo/Sender.java\",\"src/main/java/cn/wildfirechat/app/pojo/StarEvent.java\",\"src/main/java/ikidou/reflect/TypeBuilder.java\",\"src/main/java/ikidou/reflect/TypeToken.java\",\"src/main/java/ikidou/reflect/exception/TypeException.java\",\"src/main/java/ikidou/reflect/typeimpl/ParameterizedTypeImpl.java\",\"src/main/java/ikidou/reflect/typeimpl/WildcardTypeImpl.java\",\"src/main/resources/application.properties\",\"src/test/java/cn/wildfirechat/app/ApplicationTests.java\"],\"removed\":[],\"modified\":[]}}"; 26 | PushEvent pushEvent = new Gson().fromJson(event1, PushEvent.class); 27 | System.out.println(pushEvent.compare); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/github/pojo/Pusher.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.github.pojo; 2 | 3 | public class Pusher { 4 | public String name; 5 | public String email; 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/github/pojo/Repository.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.github.pojo; 2 | 3 | import java.util.Date; 4 | 5 | public class Repository { 6 | public long id; 7 | public String node_id; 8 | public String name; 9 | public String full_name; 10 | public User owner; 11 | public String html_url; 12 | public String description; 13 | public boolean fork; 14 | public String url; 15 | public String forks_url; 16 | public String keys_url; 17 | public String collaborators_url; 18 | public String teams_url; 19 | public String hooks_url; 20 | public String issue_events_url; 21 | public String events_url; 22 | public String assignees_url; 23 | public String branches_url; 24 | public String tags_url; 25 | public String blobs_url; 26 | public String git_tags_url; 27 | public String git_refs_url; 28 | public String trees_url; 29 | public String statuses_url; 30 | public String languages_url; 31 | public String stargazers_url; 32 | public String contributors_url; 33 | public String subscribers_url; 34 | public String subscription_url; 35 | public String commits_url; 36 | public String git_commits_url; 37 | public String comments_url; 38 | public String issue_comment_url; 39 | public String contents_url; 40 | public String compare_url; 41 | public String merges_url; 42 | public String archive_url; 43 | public String downloads_url; 44 | public String issues_url; 45 | public String pulls_url; 46 | public String milestones_url; 47 | public String notifications_url; 48 | public String labels_url; 49 | public String releases_url; 50 | public String deployments_url; 51 | public String git_url; 52 | public String ssh_url; 53 | public String clone_url; 54 | public String svn_url; 55 | public String homepage; 56 | public int size; 57 | public int stargazers_count; 58 | public int watchers_count; 59 | public String language; 60 | public boolean has_issues; 61 | public boolean has_projects; 62 | public boolean has_downloads; 63 | public boolean has_wiki; 64 | public boolean has_pages; 65 | public int forks_count; 66 | public String mirror_url; 67 | public boolean archived; 68 | public boolean disabled; 69 | public int open_issues_count; 70 | public License license; 71 | public int forks; 72 | public int open_issues; 73 | public int watchers; 74 | public String default_branch; 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/github/pojo/Sender.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.github.pojo; 2 | 3 | public class Sender { 4 | public String login; 5 | public long id; 6 | public String node_id; 7 | public String avatar_url; 8 | public String gravatar_id; 9 | public String url; 10 | public String html_url; 11 | public String followers_url; 12 | public String following_url; 13 | public String gists_url; 14 | public String starred_url; 15 | public String subscriptions_url; 16 | public String organizations_url; 17 | public String repos_url; 18 | public String events_url; 19 | public String received_events_url; 20 | public String type; 21 | public boolean site_admin; 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/github/pojo/StarEvent.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.github.pojo; 2 | 3 | import com.google.gson.Gson; 4 | 5 | import java.util.Date; 6 | 7 | //https://developer.github.com/v3/activity/events/types/#starevent 8 | public class StarEvent { 9 | //The action performed. Can be created or deleted. 10 | public String action; 11 | public Date starred_at; 12 | public Repository repository; 13 | public Sender sender; 14 | 15 | public static StarEvent fromJson(String jsonStr) { 16 | return new Gson().fromJson(jsonStr, StarEvent.class); 17 | } 18 | 19 | public static void main(String[] args) { 20 | String starEvent1 = "{\"action\":\"deleted\",\"starred_at\":null,\"repository\":{\"id\":218795851,\"node_id\":\"MDEwOlJlcG9zaXRvcnkyMTg3OTU4NTE=\",\"name\":\"web-chat\",\"full_name\":\"wildfirechat/web-chat\",\"private\":false,\"owner\":{\"login\":\"wildfirechat\",\"id\":33191460,\"node_id\":\"MDEyOk9yZ2FuaXphdGlvbjMzMTkxNDYw\",\"avatar_url\":\"https://avatars0.githubusercontent.com/u/33191460?v=4\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/wildfirechat\",\"html_url\":\"https://github.com/wildfirechat\",\"followers_url\":\"https://api.github.com/users/wildfirechat/followers\",\"following_url\":\"https://api.github.com/users/wildfirechat/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/wildfirechat/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/wildfirechat/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/wildfirechat/subscriptions\",\"organizations_url\":\"https://api.github.com/users/wildfirechat/orgs\",\"repos_url\":\"https://api.github.com/users/wildfirechat/repos\",\"events_url\":\"https://api.github.com/users/wildfirechat/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/wildfirechat/received_events\",\"type\":\"Organization\",\"site_admin\":false},\"html_url\":\"https://github.com/wildfirechat/web-chat\",\"description\":\"Open source IM solution. \",\"fork\":false,\"url\":\"https://api.github.com/repos/wildfirechat/web-chat\",\"forks_url\":\"https://api.github.com/repos/wildfirechat/web-chat/forks\",\"keys_url\":\"https://api.github.com/repos/wildfirechat/web-chat/keys{/key_id}\",\"collaborators_url\":\"https://api.github.com/repos/wildfirechat/web-chat/collaborators{/collaborator}\",\"teams_url\":\"https://api.github.com/repos/wildfirechat/web-chat/teams\",\"hooks_url\":\"https://api.github.com/repos/wildfirechat/web-chat/hooks\",\"issue_events_url\":\"https://api.github.com/repos/wildfirechat/web-chat/issues/events{/number}\",\"events_url\":\"https://api.github.com/repos/wildfirechat/web-chat/events\",\"assignees_url\":\"https://api.github.com/repos/wildfirechat/web-chat/assignees{/user}\",\"branches_url\":\"https://api.github.com/repos/wildfirechat/web-chat/branches{/branch}\",\"tags_url\":\"https://api.github.com/repos/wildfirechat/web-chat/tags\",\"blobs_url\":\"https://api.github.com/repos/wildfirechat/web-chat/git/blobs{/sha}\",\"git_tags_url\":\"https://api.github.com/repos/wildfirechat/web-chat/git/tags{/sha}\",\"git_refs_url\":\"https://api.github.com/repos/wildfirechat/web-chat/git/refs{/sha}\",\"trees_url\":\"https://api.github.com/repos/wildfirechat/web-chat/git/trees{/sha}\",\"statuses_url\":\"https://api.github.com/repos/wildfirechat/web-chat/statuses/{sha}\",\"languages_url\":\"https://api.github.com/repos/wildfirechat/web-chat/languages\",\"stargazers_url\":\"https://api.github.com/repos/wildfirechat/web-chat/stargazers\",\"contributors_url\":\"https://api.github.com/repos/wildfirechat/web-chat/contributors\",\"subscribers_url\":\"https://api.github.com/repos/wildfirechat/web-chat/subscribers\",\"subscription_url\":\"https://api.github.com/repos/wildfirechat/web-chat/subscription\",\"commits_url\":\"https://api.github.com/repos/wildfirechat/web-chat/commits{/sha}\",\"git_commits_url\":\"https://api.github.com/repos/wildfirechat/web-chat/git/commits{/sha}\",\"comments_url\":\"https://api.github.com/repos/wildfirechat/web-chat/comments{/number}\",\"issue_comment_url\":\"https://api.github.com/repos/wildfirechat/web-chat/issues/comments{/number}\",\"contents_url\":\"https://api.github.com/repos/wildfirechat/web-chat/contents/{+path}\",\"compare_url\":\"https://api.github.com/repos/wildfirechat/web-chat/compare/{base}...{head}\",\"merges_url\":\"https://api.github.com/repos/wildfirechat/web-chat/merges\",\"archive_url\":\"https://api.github.com/repos/wildfirechat/web-chat/{archive_format}{/ref}\",\"downloads_url\":\"https://api.github.com/repos/wildfirechat/web-chat/downloads\",\"issues_url\":\"https://api.github.com/repos/wildfirechat/web-chat/issues{/number}\",\"pulls_url\":\"https://api.github.com/repos/wildfirechat/web-chat/pulls{/number}\",\"milestones_url\":\"https://api.github.com/repos/wildfirechat/web-chat/milestones{/number}\",\"notifications_url\":\"https://api.github.com/repos/wildfirechat/web-chat/notifications{?since,all,participating}\",\"labels_url\":\"https://api.github.com/repos/wildfirechat/web-chat/labels{/name}\",\"releases_url\":\"https://api.github.com/repos/wildfirechat/web-chat/releases{/id}\",\"deployments_url\":\"https://api.github.com/repos/wildfirechat/web-chat/deployments\",\"created_at\":\"2019-10-31T15:17:35Z\",\"updated_at\":\"2020-02-23T10:34:40Z\",\"pushed_at\":\"2020-02-17T01:53:42Z\",\"git_url\":\"git://github.com/wildfirechat/web-chat.git\",\"ssh_url\":\"git@github.com:wildfirechat/web-chat.git\",\"clone_url\":\"https://github.com/wildfirechat/web-chat.git\",\"svn_url\":\"https://github.com/wildfirechat/web-chat\",\"homepage\":\"http://docs.wildfirechat.cn\",\"size\":97998,\"stargazers_count\":18,\"watchers_count\":18,\"language\":\"JavaScript\",\"has_issues\":true,\"has_projects\":true,\"has_downloads\":true,\"has_wiki\":true,\"has_pages\":false,\"forks_count\":31,\"mirror_url\":null,\"archived\":false,\"disabled\":false,\"open_issues_count\":3,\"license\":{\"key\":\"mit\",\"name\":\"MIT License\",\"spdx_id\":\"MIT\",\"url\":\"https://api.github.com/licenses/mit\",\"node_id\":\"MDc6TGljZW5zZTEz\"},\"forks\":31,\"open_issues\":3,\"watchers\":18,\"default_branch\":\"master\"},\"organization\":{\"login\":\"wildfirechat\",\"id\":33191460,\"node_id\":\"MDEyOk9yZ2FuaXphdGlvbjMzMTkxNDYw\",\"url\":\"https://api.github.com/orgs/wildfirechat\",\"repos_url\":\"https://api.github.com/orgs/wildfirechat/repos\",\"events_url\":\"https://api.github.com/orgs/wildfirechat/events\",\"hooks_url\":\"https://api.github.com/orgs/wildfirechat/hooks\",\"issues_url\":\"https://api.github.com/orgs/wildfirechat/issues\",\"members_url\":\"https://api.github.com/orgs/wildfirechat/members{/member}\",\"public_members_url\":\"https://api.github.com/orgs/wildfirechat/public_members{/member}\",\"avatar_url\":\"https://avatars0.githubusercontent.com/u/33191460?v=4\",\"description\":\"北京野火无限网络科技有限公司--专注于即时通讯技术,提供优质可控的即时通讯能力\"},\"sender\":{\"login\":\"heavyrain2012\",\"id\":34463389,\"node_id\":\"MDQ6VXNlcjM0NDYzMzg5\",\"avatar_url\":\"https://avatars0.githubusercontent.com/u/34463389?v=4\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/heavyrain2012\",\"html_url\":\"https://github.com/heavyrain2012\",\"followers_url\":\"https://api.github.com/users/heavyrain2012/followers\",\"following_url\":\"https://api.github.com/users/heavyrain2012/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/heavyrain2012/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/heavyrain2012/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/heavyrain2012/subscriptions\",\"organizations_url\":\"https://api.github.com/users/heavyrain2012/orgs\",\"repos_url\":\"https://api.github.com/users/heavyrain2012/repos\",\"events_url\":\"https://api.github.com/users/heavyrain2012/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/heavyrain2012/received_events\",\"type\":\"User\",\"site_admin\":false}}"; 21 | StarEvent deletedEvent = new Gson().fromJson(starEvent1, StarEvent.class); 22 | System.out.println(deletedEvent.action); 23 | 24 | String starEvent2 = "{\"action\":\"created\",\"starred_at\":\"2020-02-23T10:35:05Z\",\"repository\":{\"id\":218795851,\"node_id\":\"MDEwOlJlcG9zaXRvcnkyMTg3OTU4NTE=\",\"name\":\"web-chat\",\"full_name\":\"wildfirechat/web-chat\",\"private\":false,\"owner\":{\"login\":\"wildfirechat\",\"id\":33191460,\"node_id\":\"MDEyOk9yZ2FuaXphdGlvbjMzMTkxNDYw\",\"avatar_url\":\"https://avatars0.githubusercontent.com/u/33191460?v=4\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/wildfirechat\",\"html_url\":\"https://github.com/wildfirechat\",\"followers_url\":\"https://api.github.com/users/wildfirechat/followers\",\"following_url\":\"https://api.github.com/users/wildfirechat/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/wildfirechat/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/wildfirechat/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/wildfirechat/subscriptions\",\"organizations_url\":\"https://api.github.com/users/wildfirechat/orgs\",\"repos_url\":\"https://api.github.com/users/wildfirechat/repos\",\"events_url\":\"https://api.github.com/users/wildfirechat/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/wildfirechat/received_events\",\"type\":\"Organization\",\"site_admin\":false},\"html_url\":\"https://github.com/wildfirechat/web-chat\",\"description\":\"Open source IM solution. \",\"fork\":false,\"url\":\"https://api.github.com/repos/wildfirechat/web-chat\",\"forks_url\":\"https://api.github.com/repos/wildfirechat/web-chat/forks\",\"keys_url\":\"https://api.github.com/repos/wildfirechat/web-chat/keys{/key_id}\",\"collaborators_url\":\"https://api.github.com/repos/wildfirechat/web-chat/collaborators{/collaborator}\",\"teams_url\":\"https://api.github.com/repos/wildfirechat/web-chat/teams\",\"hooks_url\":\"https://api.github.com/repos/wildfirechat/web-chat/hooks\",\"issue_events_url\":\"https://api.github.com/repos/wildfirechat/web-chat/issues/events{/number}\",\"events_url\":\"https://api.github.com/repos/wildfirechat/web-chat/events\",\"assignees_url\":\"https://api.github.com/repos/wildfirechat/web-chat/assignees{/user}\",\"branches_url\":\"https://api.github.com/repos/wildfirechat/web-chat/branches{/branch}\",\"tags_url\":\"https://api.github.com/repos/wildfirechat/web-chat/tags\",\"blobs_url\":\"https://api.github.com/repos/wildfirechat/web-chat/git/blobs{/sha}\",\"git_tags_url\":\"https://api.github.com/repos/wildfirechat/web-chat/git/tags{/sha}\",\"git_refs_url\":\"https://api.github.com/repos/wildfirechat/web-chat/git/refs{/sha}\",\"trees_url\":\"https://api.github.com/repos/wildfirechat/web-chat/git/trees{/sha}\",\"statuses_url\":\"https://api.github.com/repos/wildfirechat/web-chat/statuses/{sha}\",\"languages_url\":\"https://api.github.com/repos/wildfirechat/web-chat/languages\",\"stargazers_url\":\"https://api.github.com/repos/wildfirechat/web-chat/stargazers\",\"contributors_url\":\"https://api.github.com/repos/wildfirechat/web-chat/contributors\",\"subscribers_url\":\"https://api.github.com/repos/wildfirechat/web-chat/subscribers\",\"subscription_url\":\"https://api.github.com/repos/wildfirechat/web-chat/subscription\",\"commits_url\":\"https://api.github.com/repos/wildfirechat/web-chat/commits{/sha}\",\"git_commits_url\":\"https://api.github.com/repos/wildfirechat/web-chat/git/commits{/sha}\",\"comments_url\":\"https://api.github.com/repos/wildfirechat/web-chat/comments{/number}\",\"issue_comment_url\":\"https://api.github.com/repos/wildfirechat/web-chat/issues/comments{/number}\",\"contents_url\":\"https://api.github.com/repos/wildfirechat/web-chat/contents/{+path}\",\"compare_url\":\"https://api.github.com/repos/wildfirechat/web-chat/compare/{base}...{head}\",\"merges_url\":\"https://api.github.com/repos/wildfirechat/web-chat/merges\",\"archive_url\":\"https://api.github.com/repos/wildfirechat/web-chat/{archive_format}{/ref}\",\"downloads_url\":\"https://api.github.com/repos/wildfirechat/web-chat/downloads\",\"issues_url\":\"https://api.github.com/repos/wildfirechat/web-chat/issues{/number}\",\"pulls_url\":\"https://api.github.com/repos/wildfirechat/web-chat/pulls{/number}\",\"milestones_url\":\"https://api.github.com/repos/wildfirechat/web-chat/milestones{/number}\",\"notifications_url\":\"https://api.github.com/repos/wildfirechat/web-chat/notifications{?since,all,participating}\",\"labels_url\":\"https://api.github.com/repos/wildfirechat/web-chat/labels{/name}\",\"releases_url\":\"https://api.github.com/repos/wildfirechat/web-chat/releases{/id}\",\"deployments_url\":\"https://api.github.com/repos/wildfirechat/web-chat/deployments\",\"created_at\":\"2019-10-31T15:17:35Z\",\"updated_at\":\"2020-02-23T10:35:05Z\",\"pushed_at\":\"2020-02-17T01:53:42Z\",\"git_url\":\"git://github.com/wildfirechat/web-chat.git\",\"ssh_url\":\"git@github.com:wildfirechat/web-chat.git\",\"clone_url\":\"https://github.com/wildfirechat/web-chat.git\",\"svn_url\":\"https://github.com/wildfirechat/web-chat\",\"homepage\":\"http://docs.wildfirechat.cn\",\"size\":97998,\"stargazers_count\":19,\"watchers_count\":19,\"language\":\"JavaScript\",\"has_issues\":true,\"has_projects\":true,\"has_downloads\":true,\"has_wiki\":true,\"has_pages\":false,\"forks_count\":31,\"mirror_url\":null,\"archived\":false,\"disabled\":false,\"open_issues_count\":3,\"license\":{\"key\":\"mit\",\"name\":\"MIT License\",\"spdx_id\":\"MIT\",\"url\":\"https://api.github.com/licenses/mit\",\"node_id\":\"MDc6TGljZW5zZTEz\"},\"forks\":31,\"open_issues\":3,\"watchers\":19,\"default_branch\":\"master\"},\"organization\":{\"login\":\"wildfirechat\",\"id\":33191460,\"node_id\":\"MDEyOk9yZ2FuaXphdGlvbjMzMTkxNDYw\",\"url\":\"https://api.github.com/orgs/wildfirechat\",\"repos_url\":\"https://api.github.com/orgs/wildfirechat/repos\",\"events_url\":\"https://api.github.com/orgs/wildfirechat/events\",\"hooks_url\":\"https://api.github.com/orgs/wildfirechat/hooks\",\"issues_url\":\"https://api.github.com/orgs/wildfirechat/issues\",\"members_url\":\"https://api.github.com/orgs/wildfirechat/members{/member}\",\"public_members_url\":\"https://api.github.com/orgs/wildfirechat/public_members{/member}\",\"avatar_url\":\"https://avatars0.githubusercontent.com/u/33191460?v=4\",\"description\":\"北京野火无限网络科技有限公司--专注于即时通讯技术,提供优质可控的即时通讯能力\"},\"sender\":{\"login\":\"heavyrain2012\",\"id\":34463389,\"node_id\":\"MDQ6VXNlcjM0NDYzMzg5\",\"avatar_url\":\"https://avatars0.githubusercontent.com/u/34463389?v=4\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/heavyrain2012\",\"html_url\":\"https://github.com/heavyrain2012\",\"followers_url\":\"https://api.github.com/users/heavyrain2012/followers\",\"following_url\":\"https://api.github.com/users/heavyrain2012/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/heavyrain2012/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/heavyrain2012/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/heavyrain2012/subscriptions\",\"organizations_url\":\"https://api.github.com/users/heavyrain2012/orgs\",\"repos_url\":\"https://api.github.com/users/heavyrain2012/repos\",\"events_url\":\"https://api.github.com/users/heavyrain2012/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/heavyrain2012/received_events\",\"type\":\"User\",\"site_admin\":false}}"; 25 | StarEvent starredEvent = new Gson().fromJson(starEvent2, StarEvent.class); 26 | System.out.println(starredEvent.action); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/github/pojo/User.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.github.pojo; 2 | 3 | public class User { 4 | public String login; 5 | public long id; 6 | public String node_id; 7 | public String avatar_url; 8 | public String gravatar_id; 9 | public String url; 10 | public String html_url; 11 | public String followers_url; 12 | public String following_url; 13 | public String gists_url; 14 | public String starred_url; 15 | public String subscriptions_url; 16 | public String organizations_url; 17 | public String repos_url; 18 | public String events_url; 19 | public String received_events_url; 20 | public String type; 21 | public String site_admin; 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/github/pojo/WatchEvent.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.github.pojo; 2 | 3 | import com.google.gson.Gson; 4 | 5 | //https://developer.github.com/v3/activity/events/types/#watchevent 6 | public class WatchEvent { 7 | //The action that was performed. Currently, can only be started. 8 | public String action; 9 | public Repository repository; 10 | public User sender; 11 | 12 | public static WatchEvent fromJson(String jsonStr) { 13 | return new Gson().fromJson(jsonStr, WatchEvent.class); 14 | } 15 | 16 | public static void main(String[] args) { 17 | String event = "{\"action\":\"started\",\"repository\":{\"id\":172194045,\"node_id\":\"MDEwOlJlcG9zaXRvcnkxNzIxOTQwNDU=\",\"name\":\"pc-chat\",\"full_name\":\"wildfirechat/pc-chat\",\"private\":false,\"owner\":{\"login\":\"wildfirechat\",\"id\":33191460,\"node_id\":\"MDEyOk9yZ2FuaXphdGlvbjMzMTkxNDYw\",\"avatar_url\":\"https://avatars0.githubusercontent.com/u/33191460?v=4\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/wildfirechat\",\"html_url\":\"https://github.com/wildfirechat\",\"followers_url\":\"https://api.github.com/users/wildfirechat/followers\",\"following_url\":\"https://api.github.com/users/wildfirechat/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/wildfirechat/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/wildfirechat/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/wildfirechat/subscriptions\",\"organizations_url\":\"https://api.github.com/users/wildfirechat/orgs\",\"repos_url\":\"https://api.github.com/users/wildfirechat/repos\",\"events_url\":\"https://api.github.com/users/wildfirechat/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/wildfirechat/received_events\",\"type\":\"Organization\",\"site_admin\":false},\"html_url\":\"https://github.com/wildfirechat/pc-chat\",\"description\":\"Open source IM solution. \",\"fork\":false,\"url\":\"https://api.github.com/repos/wildfirechat/pc-chat\",\"forks_url\":\"https://api.github.com/repos/wildfirechat/pc-chat/forks\",\"keys_url\":\"https://api.github.com/repos/wildfirechat/pc-chat/keys{/key_id}\",\"collaborators_url\":\"https://api.github.com/repos/wildfirechat/pc-chat/collaborators{/collaborator}\",\"teams_url\":\"https://api.github.com/repos/wildfirechat/pc-chat/teams\",\"hooks_url\":\"https://api.github.com/repos/wildfirechat/pc-chat/hooks\",\"issue_events_url\":\"https://api.github.com/repos/wildfirechat/pc-chat/issues/events{/number}\",\"events_url\":\"https://api.github.com/repos/wildfirechat/pc-chat/events\",\"assignees_url\":\"https://api.github.com/repos/wildfirechat/pc-chat/assignees{/user}\",\"branches_url\":\"https://api.github.com/repos/wildfirechat/pc-chat/branches{/branch}\",\"tags_url\":\"https://api.github.com/repos/wildfirechat/pc-chat/tags\",\"blobs_url\":\"https://api.github.com/repos/wildfirechat/pc-chat/git/blobs{/sha}\",\"git_tags_url\":\"https://api.github.com/repos/wildfirechat/pc-chat/git/tags{/sha}\",\"git_refs_url\":\"https://api.github.com/repos/wildfirechat/pc-chat/git/refs{/sha}\",\"trees_url\":\"https://api.github.com/repos/wildfirechat/pc-chat/git/trees{/sha}\",\"statuses_url\":\"https://api.github.com/repos/wildfirechat/pc-chat/statuses/{sha}\",\"languages_url\":\"https://api.github.com/repos/wildfirechat/pc-chat/languages\",\"stargazers_url\":\"https://api.github.com/repos/wildfirechat/pc-chat/stargazers\",\"contributors_url\":\"https://api.github.com/repos/wildfirechat/pc-chat/contributors\",\"subscribers_url\":\"https://api.github.com/repos/wildfirechat/pc-chat/subscribers\",\"subscription_url\":\"https://api.github.com/repos/wildfirechat/pc-chat/subscription\",\"commits_url\":\"https://api.github.com/repos/wildfirechat/pc-chat/commits{/sha}\",\"git_commits_url\":\"https://api.github.com/repos/wildfirechat/pc-chat/git/commits{/sha}\",\"comments_url\":\"https://api.github.com/repos/wildfirechat/pc-chat/comments{/number}\",\"issue_comment_url\":\"https://api.github.com/repos/wildfirechat/pc-chat/issues/comments{/number}\",\"contents_url\":\"https://api.github.com/repos/wildfirechat/pc-chat/contents/{+path}\",\"compare_url\":\"https://api.github.com/repos/wildfirechat/pc-chat/compare/{base}...{head}\",\"merges_url\":\"https://api.github.com/repos/wildfirechat/pc-chat/merges\",\"archive_url\":\"https://api.github.com/repos/wildfirechat/pc-chat/{archive_format}{/ref}\",\"downloads_url\":\"https://api.github.com/repos/wildfirechat/pc-chat/downloads\",\"issues_url\":\"https://api.github.com/repos/wildfirechat/pc-chat/issues{/number}\",\"pulls_url\":\"https://api.github.com/repos/wildfirechat/pc-chat/pulls{/number}\",\"milestones_url\":\"https://api.github.com/repos/wildfirechat/pc-chat/milestones{/number}\",\"notifications_url\":\"https://api.github.com/repos/wildfirechat/pc-chat/notifications{?since,all,participating}\",\"labels_url\":\"https://api.github.com/repos/wildfirechat/pc-chat/labels{/name}\",\"releases_url\":\"https://api.github.com/repos/wildfirechat/pc-chat/releases{/id}\",\"deployments_url\":\"https://api.github.com/repos/wildfirechat/pc-chat/deployments\",\"created_at\":\"2019-02-23T09:08:03Z\",\"updated_at\":\"2020-02-24T01:15:25Z\",\"pushed_at\":\"2020-02-23T08:31:54Z\",\"git_url\":\"git://github.com/wildfirechat/pc-chat.git\",\"ssh_url\":\"git@github.com:wildfirechat/pc-chat.git\",\"clone_url\":\"https://github.com/wildfirechat/pc-chat.git\",\"svn_url\":\"https://github.com/wildfirechat/pc-chat\",\"homepage\":\"http://docs.wildfirechat.cn\",\"size\":172881,\"stargazers_count\":268,\"watchers_count\":268,\"language\":\"JavaScript\",\"has_issues\":true,\"has_projects\":true,\"has_downloads\":true,\"has_wiki\":true,\"has_pages\":false,\"forks_count\":199,\"mirror_url\":null,\"archived\":false,\"disabled\":false,\"open_issues_count\":7,\"license\":{\"key\":\"mit\",\"name\":\"MIT License\",\"spdx_id\":\"MIT\",\"url\":\"https://api.github.com/licenses/mit\",\"node_id\":\"MDc6TGljZW5zZTEz\"},\"forks\":199,\"open_issues\":7,\"watchers\":268,\"default_branch\":\"master\"},\"organization\":{\"login\":\"wildfirechat\",\"id\":33191460,\"node_id\":\"MDEyOk9yZ2FuaXphdGlvbjMzMTkxNDYw\",\"url\":\"https://api.github.com/orgs/wildfirechat\",\"repos_url\":\"https://api.github.com/orgs/wildfirechat/repos\",\"events_url\":\"https://api.github.com/orgs/wildfirechat/events\",\"hooks_url\":\"https://api.github.com/orgs/wildfirechat/hooks\",\"issues_url\":\"https://api.github.com/orgs/wildfirechat/issues\",\"members_url\":\"https://api.github.com/orgs/wildfirechat/members{/member}\",\"public_members_url\":\"https://api.github.com/orgs/wildfirechat/public_members{/member}\",\"avatar_url\":\"https://avatars0.githubusercontent.com/u/33191460?v=4\",\"description\":\"北京野火无限网络科技有限公司--专注于即时通讯技术,提供优质可控的即时通讯能力\"},\"sender\":{\"login\":\"longshadian\",\"id\":1725317,\"node_id\":\"MDQ6VXNlcjE3MjUzMTc=\",\"avatar_url\":\"https://avatars0.githubusercontent.com/u/1725317?v=4\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/longshadian\",\"html_url\":\"https://github.com/longshadian\",\"followers_url\":\"https://api.github.com/users/longshadian/followers\",\"following_url\":\"https://api.github.com/users/longshadian/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/longshadian/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/longshadian/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/longshadian/subscriptions\",\"organizations_url\":\"https://api.github.com/users/longshadian/orgs\",\"repos_url\":\"https://api.github.com/users/longshadian/repos\",\"events_url\":\"https://api.github.com/users/longshadian/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/longshadian/received_events\",\"type\":\"User\",\"site_admin\":false}}"; 18 | WatchEvent watchEvent = fromJson(event); 19 | System.out.println(watchEvent.action); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/gitlab/GitLabWebhook.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.gitlab; 2 | 3 | import cn.wildfirechat.app.webhook.IWebhook; 4 | import cn.wildfirechat.app.webhook.gitlab.pojo.*; 5 | import cn.wildfirechat.pojos.MessagePayload; 6 | import com.google.gson.Gson; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | import javax.servlet.http.HttpServletRequest; 11 | 12 | public class GitLabWebhook implements IWebhook { 13 | private static final Logger LOG = LoggerFactory.getLogger(GitLabWebhook.class); 14 | @Override 15 | public String invokeCommand() { 16 | return "/gitlab"; 17 | } 18 | 19 | @Override 20 | public Object handleWebhookPost(HttpServletRequest request, String user, String payload, SendMessageCallback callback) { 21 | String event = request.getHeader("X-Gitlab-Event"); 22 | LOG.info("on receive message {}, event {}", payload, event); 23 | 24 | String message = null; 25 | 26 | MessagePayload messagePayload = new MessagePayload(); 27 | messagePayload.setType(1); 28 | 29 | //https://gitee.com/help/articles/4271#article-header0 30 | try { 31 | if (event.equals("Push Hook")) { 32 | PushEvent pushEvent = new Gson().fromJson(payload, PushEvent.class); 33 | message = pushEvent.user_name + " push " + pushEvent.total_commits_count + " commit(s) 到项目 " + pushEvent.repository.name; 34 | for (Commit commit: pushEvent.commits) { 35 | message += "\n"; 36 | message += "\nTitle: " + commit.title; 37 | message += "\nMessage: " + commit.message; 38 | message += "\nUrl: " + commit.url; 39 | } 40 | } else if(event.equals("Tag Push Hook")) { 41 | TagEvent tagEvent = new Gson().fromJson(payload, TagEvent.class); 42 | message = tagEvent.user_name + " 在项目 " + tagEvent.repository.name + " " + tagEvent.object_kind + " " + tagEvent.ref; 43 | } else if(event.equals("Issue Hook")) { 44 | IssueEvent issueEvent = new Gson().fromJson(payload, IssueEvent.class); 45 | message = issueEvent.user.name + " 在项目 " + issueEvent.repository.name + " 提交了issue"; 46 | message += "\nTitle: " + issueEvent.object_attributes.title; 47 | message += "\nMessage: " + issueEvent.object_attributes.description; 48 | message += "\nUrl: " + issueEvent.object_attributes.url; 49 | } else if(event.equals("Note Hook")) { 50 | NoteEvent noteEvent = new Gson().fromJson(payload, NoteEvent.class); 51 | message = noteEvent.user.name + " 在项目 " + noteEvent.repository.name + " 评论了 " + noteEvent.object_attributes.noteable_type; 52 | message += "\nMessage: " + noteEvent.object_attributes.note; 53 | if(noteEvent.object_attributes.noteable_type.equalsIgnoreCase("Commit")) { 54 | message += "\nCommit title: " + noteEvent.commit.title; 55 | message += "\nCommit message: " + noteEvent.commit.message; 56 | message += "\nCommit url: " + noteEvent.commit.url; 57 | } else if(noteEvent.object_attributes.noteable_type.equalsIgnoreCase("MergeRequest")) { 58 | message += "\nMergeRequest title: " + noteEvent.merge_request.description; 59 | message += "\nMergeRequest state: " + noteEvent.merge_request.state; 60 | message += "\nMergeRequest merge_status: " + noteEvent.merge_request.merge_status; 61 | } else if(noteEvent.object_attributes.noteable_type.equalsIgnoreCase("Issue")) { 62 | message += "\nIssue title: " + noteEvent.issue.title; 63 | message += "\nIssue message: " + noteEvent.issue.body; 64 | message += "\nIssue url: " + noteEvent.issue.html_url; 65 | } else if(noteEvent.object_attributes.noteable_type.equalsIgnoreCase("Snippet")) { 66 | message += "\nSnippet title: " + noteEvent.snippet.title; 67 | message += "\nSnippet message: " + noteEvent.snippet.content; 68 | message += "\nSnippet file: " + noteEvent.snippet.file_name; 69 | } 70 | } else if(event.equals("Merge Request Hook")) { 71 | MergeRequestEvent mergeRequestEvent = new Gson().fromJson(payload, MergeRequestEvent.class); 72 | message = mergeRequestEvent.user.name + " merge request 在项目 " + mergeRequestEvent.repository.name; 73 | message += "\nTitle: " + mergeRequestEvent.object_attributes.title; 74 | message += "\ndescription: " + mergeRequestEvent.object_attributes.description; 75 | message += "\nsource_branch: " + mergeRequestEvent.object_attributes.source_branch; 76 | message += "\ntarget_branch: " + mergeRequestEvent.object_attributes.target_branch; 77 | } 78 | } catch (Exception e) { 79 | e.printStackTrace(); 80 | messagePayload.setSearchableContent("糟糕,处理gitlab事件出错了:" + e.getMessage()); 81 | callback.sendMessage(messagePayload); 82 | } 83 | 84 | if (message == null) { 85 | messagePayload.setSearchableContent("你收到了一个gitlab事件:" + event); 86 | callback.sendMessage(messagePayload); 87 | messagePayload.setSearchableContent(payload); 88 | callback.sendMessage(messagePayload); 89 | } else { 90 | messagePayload.setSearchableContent(message); 91 | callback.sendMessage(messagePayload); 92 | } 93 | return "ok"; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/gitlab/pojo/Author.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.gitlab.pojo; 2 | 3 | public class Author { 4 | public String name; 5 | public String email; 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/gitlab/pojo/Commit.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.gitlab.pojo; 2 | 3 | public class Commit { 4 | /* 5 | "id": "b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327", 6 | "message": "Update Catalan translation to e38cb41.\n\nSee https://gitlab.com/gitlab-org/gitlab for more information", 7 | "title": "Update Catalan translation to e38cb41.", 8 | "timestamp": "2011-12-12T14:27:31+02:00", 9 | "url": "http://example.com/mike/diaspora/commit/b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327", 10 | "author": { 11 | "name": "Jordi Mallach", 12 | "email": "jordi@softcatala.org" 13 | }, 14 | "added": ["CHANGELOG"], 15 | "modified": ["app/controller/application.rb"], 16 | "removed": [] 17 | */ 18 | public String id; 19 | public String message; 20 | public String title; 21 | public String timestamp; 22 | public String url; 23 | public Author author; 24 | public String[] added; 25 | public String[] modified; 26 | public String[] removed; 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/gitlab/pojo/IssueEvent.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.gitlab.pojo; 2 | 3 | public class IssueEvent { 4 | public User user; 5 | public Project project; 6 | public Repository repository; 7 | public IssueObjectAttributes object_attributes; 8 | public User[] assignees; 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/gitlab/pojo/IssueObjectAttributes.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.gitlab.pojo; 2 | 3 | public class IssueObjectAttributes { 4 | public String title; 5 | public String description; 6 | public String url; 7 | public String state; 8 | public String action; 9 | /* 10 | "id": 301, 11 | "title": "New API: create/update/delete file", 12 | "assignee_ids": [51], 13 | "assignee_id": 51, 14 | "author_id": 51, 15 | "project_id": 14, 16 | "created_at": "2013-12-03T17:15:43Z", 17 | "updated_at": "2013-12-03T17:15:43Z", 18 | "updated_by_id": 1, 19 | "last_edited_at": null, 20 | "last_edited_by_id": null, 21 | "relative_position": 0, 22 | "description": "Create new API for manipulations with repository", 23 | "milestone_id": null, 24 | "state_id": 1, 25 | "confidential": false, 26 | "discussion_locked": true, 27 | "due_date": null, 28 | "moved_to_id": null, 29 | "duplicated_to_id": null, 30 | "time_estimate": 0, 31 | "total_time_spent": 0, 32 | "human_total_time_spent": null, 33 | "human_time_estimate": null, 34 | "weight": null, 35 | "iid": 23, 36 | "url": "http://example.com/diaspora/issues/23", 37 | "state": "opened", 38 | "action": "open", 39 | */ 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/gitlab/pojo/Label.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.gitlab.pojo; 2 | 3 | public class Label { 4 | /* 5 | "id": 206, 6 | "title": "API", 7 | "color": "#ffffff", 8 | "project_id": 14, 9 | "created_at": "2013-12-03T17:15:43Z", 10 | "updated_at": "2013-12-03T17:15:43Z", 11 | "template": false, 12 | "description": "API related issues", 13 | "type": "ProjectLabel", 14 | "group_id": 41 15 | */ 16 | public long id; 17 | public String title; 18 | public String color; 19 | public long project_id; 20 | public String created_at; 21 | public String updated_at; 22 | public boolean template; 23 | public String description; 24 | public String type; 25 | public long group_id; 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/gitlab/pojo/MergeRequest.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.gitlab.pojo; 2 | 3 | public class MergeRequest { 4 | public String target_branch; 5 | public String source_branch; 6 | public String state; 7 | public String title; 8 | public String merge_status; 9 | public String description; 10 | public Repository source; 11 | public Repository target; 12 | public Commit last_commit; 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/gitlab/pojo/MergeRequestEvent.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.gitlab.pojo; 2 | 3 | public class MergeRequestEvent { 4 | public User user; 5 | public Repository repository; 6 | public MergeRequest object_attributes; 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/gitlab/pojo/NoteEvent.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.gitlab.pojo; 2 | 3 | import cn.wildfirechat.app.webhook.gitee.pojo.Issue; 4 | 5 | public class NoteEvent { 6 | public User user; 7 | public Project project; 8 | public Repository repository; 9 | public NoteObjectAttributes object_attributes; 10 | public Commit commit; 11 | public MergeRequest merge_request; 12 | public Issue issue; 13 | public Snippet snippet; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/gitlab/pojo/NoteObjectAttributes.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.gitlab.pojo; 2 | 3 | public class NoteObjectAttributes { 4 | /* 5 | "id": 1244, 6 | "note": "This MR needs work.", 7 | "noteable_type": "MergeRequest", 8 | "author_id": 1, 9 | "created_at": "2015-05-17 18:21:36 UTC", 10 | "updated_at": "2015-05-17 18:21:36 UTC", 11 | "project_id": 5, 12 | "attachment": null, 13 | "line_code": null, 14 | "commit_id": "", 15 | "noteable_id": 7, 16 | "system": false, 17 | "st_diff": null, 18 | "url": "http://example.com/gitlab-org/gitlab-test/merge_requests/1#note_1244" 19 | */ 20 | public long id; 21 | public String note; 22 | public String noteable_type; 23 | public String url; 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/gitlab/pojo/Project.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.gitlab.pojo; 2 | 3 | public class Project { 4 | /* 5 | "id": 15, 6 | "name":"Diaspora", 7 | "description":"", 8 | "web_url":"http://example.com/mike/diaspora", 9 | "avatar_url":null, 10 | "git_ssh_url":"git@example.com:mike/diaspora.git", 11 | "git_http_url":"http://example.com/mike/diaspora.git", 12 | "namespace":"Mike", 13 | "visibility_level":0, 14 | "path_with_namespace":"mike/diaspora", 15 | "default_branch":"master", 16 | "homepage":"http://example.com/mike/diaspora", 17 | "url":"git@example.com:mike/diaspora.git", 18 | "ssh_url":"git@example.com:mike/diaspora.git", 19 | "http_url":"http://example.com/mike/diaspora.git" 20 | */ 21 | public long id; 22 | public String name; 23 | public String description; 24 | public String web_url; 25 | public String avatar_url; 26 | public String git_ssh_url; 27 | public String git_http_url; 28 | public String namespace; 29 | public int visibility_level; 30 | public String path_with_namespace; 31 | public String default_branch; 32 | public String homepage; 33 | public String url; 34 | public String ssh_url; 35 | public String http_url; 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/gitlab/pojo/PushEvent.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.gitlab.pojo; 2 | 3 | public class PushEvent { 4 | public String user_name; 5 | public Repository repository; 6 | public Commit[] commits; 7 | public int total_commits_count; 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/gitlab/pojo/Repository.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.gitlab.pojo; 2 | 3 | public class Repository { 4 | /* 5 | "name": "Gitlab Test", 6 | "url": "http://example.com/gitlabhq/gitlab-test.git", 7 | "description": "Aut reprehenderit ut est.", 8 | "homepage": "http://example.com/gitlabhq/gitlab-test" 9 | */ 10 | public String name; 11 | public String url; 12 | public String description; 13 | public String homepage; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/gitlab/pojo/Snippet.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.gitlab.pojo; 2 | 3 | public class Snippet { 4 | /* 5 | "id": 53, 6 | "title": "test", 7 | "content": "puts 'Hello world'", 8 | "author_id": 1, 9 | "project_id": 5, 10 | "created_at": "2015-04-09 02:40:38 UTC", 11 | "updated_at": "2015-04-09 02:40:38 UTC", 12 | "file_name": "test.rb", 13 | "expires_at": null, 14 | "type": "ProjectSnippet", 15 | "visibility_level": 0 16 | */ 17 | public String title; 18 | public String content; 19 | public String file_name; 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/gitlab/pojo/TagEvent.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.gitlab.pojo; 2 | 3 | public class TagEvent { 4 | public String user_name; 5 | public String ref; 6 | public Repository repository; 7 | public String object_kind; 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/cn/wildfirechat/app/webhook/gitlab/pojo/User.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app.webhook.gitlab.pojo; 2 | 3 | public class User { 4 | /* 5 | "id": 1, 6 | "name": "Administrator", 7 | "username": "root", 8 | "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon", 9 | "email": "admin@example.com" 10 | */ 11 | public long id; 12 | public String name; 13 | public String username; 14 | public String avatar_url; 15 | public String email; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/ikidou/reflect/TypeBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 ikidou 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ikidou.reflect; 18 | 19 | import java.lang.reflect.Type; 20 | import java.util.ArrayList; 21 | import java.util.List; 22 | 23 | import ikidou.reflect.exception.TypeException; 24 | import ikidou.reflect.typeimpl.ParameterizedTypeImpl; 25 | import ikidou.reflect.typeimpl.WildcardTypeImpl; 26 | 27 | public class TypeBuilder { 28 | private final TypeBuilder parent; 29 | private final Class raw; 30 | private final List args = new ArrayList<>(); 31 | 32 | 33 | private TypeBuilder(Class raw, TypeBuilder parent) { 34 | assert raw != null; 35 | this.raw = raw; 36 | this.parent = parent; 37 | } 38 | 39 | public static TypeBuilder newInstance(Class raw) { 40 | return new TypeBuilder(raw, null); 41 | } 42 | 43 | private static TypeBuilder newInstance(Class raw, TypeBuilder parent) { 44 | return new TypeBuilder(raw, parent); 45 | } 46 | 47 | 48 | public TypeBuilder beginSubType(Class raw) { 49 | return newInstance(raw, this); 50 | } 51 | 52 | public TypeBuilder endSubType() { 53 | if (parent == null) { 54 | throw new TypeException("expect beginSubType() before endSubType()"); 55 | } 56 | 57 | parent.addTypeParam(getType()); 58 | 59 | return parent; 60 | } 61 | 62 | public TypeBuilder addTypeParam(Class clazz) { 63 | return addTypeParam((Type) clazz); 64 | } 65 | 66 | public TypeBuilder addTypeParamExtends(Class... classes) { 67 | if (classes == null) { 68 | throw new NullPointerException("addTypeParamExtends() expect not null Class"); 69 | } 70 | 71 | WildcardTypeImpl wildcardType = new WildcardTypeImpl(null, classes); 72 | 73 | return addTypeParam(wildcardType); 74 | } 75 | 76 | public TypeBuilder addTypeParamSuper(Class... classes) { 77 | if (classes == null) { 78 | throw new NullPointerException("addTypeParamSuper() expect not null Class"); 79 | } 80 | 81 | WildcardTypeImpl wildcardType = new WildcardTypeImpl(classes, null); 82 | 83 | return addTypeParam(wildcardType); 84 | } 85 | 86 | public TypeBuilder addTypeParam(Type type) { 87 | if (type == null) { 88 | throw new NullPointerException("addTypeParam expect not null Type"); 89 | } 90 | 91 | args.add(type); 92 | 93 | return this; 94 | } 95 | 96 | public Type build() { 97 | if (parent != null) { 98 | throw new TypeException("expect endSubType() before build()"); 99 | } 100 | 101 | return getType(); 102 | } 103 | 104 | private Type getType() { 105 | if (args.isEmpty()) { 106 | return raw; 107 | } 108 | return new ParameterizedTypeImpl(raw, args.toArray(new Type[args.size()]), null); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/main/java/ikidou/reflect/TypeToken.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 ikidou 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ikidou.reflect; 18 | 19 | import java.lang.reflect.ParameterizedType; 20 | import java.lang.reflect.Type; 21 | 22 | import ikidou.reflect.exception.TypeException; 23 | 24 | public abstract class TypeToken { 25 | private final Type type; 26 | 27 | public TypeToken() { 28 | Type superclass = getClass().getGenericSuperclass(); 29 | if (superclass instanceof Class) { 30 | throw new TypeException("No generics found!"); 31 | } 32 | ParameterizedType type = (ParameterizedType) superclass; 33 | this.type = type.getActualTypeArguments()[0]; 34 | } 35 | 36 | public Type getType() { 37 | return type; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/ikidou/reflect/exception/TypeException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 ikidou 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ikidou.reflect.exception; 18 | 19 | public class TypeException extends RuntimeException { 20 | public TypeException() { 21 | } 22 | 23 | public TypeException(String message) { 24 | super(message); 25 | } 26 | 27 | public TypeException(String message, Throwable cause) { 28 | super(message, cause); 29 | } 30 | 31 | public TypeException(Throwable cause) { 32 | super(cause); 33 | } 34 | 35 | public TypeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { 36 | super(message, cause, enableSuppression, writableStackTrace); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/ikidou/reflect/typeimpl/ParameterizedTypeImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 ikidou 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ikidou.reflect.typeimpl; 18 | 19 | import java.lang.reflect.ParameterizedType; 20 | import java.lang.reflect.Type; 21 | import java.lang.reflect.TypeVariable; 22 | import java.util.Arrays; 23 | 24 | import ikidou.reflect.exception.TypeException; 25 | 26 | @SuppressWarnings("SpellCheckingInspection") 27 | public class ParameterizedTypeImpl implements ParameterizedType { 28 | private final Class raw; 29 | private final Type[] args; 30 | private final Type owner; 31 | 32 | public ParameterizedTypeImpl(Class raw, Type[] args, Type owner) { 33 | this.raw = raw; 34 | this.args = args != null ? args : new Type[0]; 35 | this.owner = owner; 36 | checkArgs(); 37 | } 38 | 39 | private void checkArgs() { 40 | if (raw == null) { 41 | throw new TypeException("raw class can't be null"); 42 | } 43 | TypeVariable[] typeParameters = raw.getTypeParameters(); 44 | if (args.length != 0 && typeParameters.length != args.length) { 45 | throw new TypeException(raw.getName() + " expect " + typeParameters.length + " arg(s), got " + args.length); 46 | } 47 | } 48 | 49 | @Override 50 | public Type[] getActualTypeArguments() { 51 | return args; 52 | } 53 | 54 | @Override 55 | public Type getRawType() { 56 | return raw; 57 | } 58 | 59 | @Override 60 | public Type getOwnerType() { 61 | return owner; 62 | } 63 | 64 | @Override 65 | public String toString() { 66 | StringBuilder sb = new StringBuilder(); 67 | sb.append(raw.getName()); 68 | if (args.length != 0) { 69 | sb.append('<'); 70 | for (int i = 0; i < args.length; i++) { 71 | if (i != 0) { 72 | sb.append(", "); 73 | } 74 | Type type = args[i]; 75 | if (type instanceof Class) { 76 | Class clazz = (Class) type; 77 | 78 | if (clazz.isArray()) { 79 | int count = 0; 80 | do { 81 | count++; 82 | clazz = clazz.getComponentType(); 83 | } while (clazz.isArray()); 84 | 85 | sb.append(clazz.getName()); 86 | 87 | for (int j = count; j > 0; j--) { 88 | sb.append("[]"); 89 | } 90 | } else { 91 | sb.append(clazz.getName()); 92 | } 93 | } else { 94 | sb.append(args[i].toString()); 95 | } 96 | } 97 | sb.append('>'); 98 | } 99 | return sb.toString(); 100 | } 101 | 102 | @Override 103 | public boolean equals(Object o) { 104 | if (this == o) return true; 105 | if (o == null || getClass() != o.getClass()) return false; 106 | 107 | ParameterizedTypeImpl that = (ParameterizedTypeImpl) o; 108 | 109 | if (!raw.equals(that.raw)) return false; 110 | // Probably incorrect - comparing Object[] arrays with Arrays.equals 111 | if (!Arrays.equals(args, that.args)) return false; 112 | return owner != null ? owner.equals(that.owner) : that.owner == null; 113 | 114 | } 115 | 116 | @Override 117 | public int hashCode() { 118 | int result = raw.hashCode(); 119 | result = 31 * result + Arrays.hashCode(args); 120 | result = 31 * result + (owner != null ? owner.hashCode() : 0); 121 | return result; 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/main/java/ikidou/reflect/typeimpl/WildcardTypeImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 ikidou 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ikidou.reflect.typeimpl; 18 | 19 | import java.lang.reflect.Type; 20 | import java.lang.reflect.WildcardType; 21 | import java.util.Arrays; 22 | 23 | public class WildcardTypeImpl implements WildcardType { 24 | private final Class[] upper; 25 | private final Class[] lower; 26 | 27 | public WildcardTypeImpl(Class[] lower, Class[] upper) { 28 | this.lower = lower != null ? lower : new Class[0]; 29 | this.upper = upper != null ? upper : new Class[0]; 30 | 31 | checkArgs(); 32 | } 33 | 34 | private void checkArgs() { 35 | if (lower.length == 0 && upper.length == 0) { 36 | throw new IllegalArgumentException("lower or upper can't be null"); 37 | } 38 | 39 | checkArgs(lower); 40 | checkArgs(upper); 41 | } 42 | 43 | private void checkArgs(Class[] args) { 44 | for (int i = 1; i < args.length; i++) { 45 | Class clazz = args[i]; 46 | if (!clazz.isInterface()) { 47 | throw new IllegalArgumentException(clazz.getName() + " not a interface!"); 48 | } 49 | } 50 | } 51 | 52 | @Override 53 | public Type[] getUpperBounds() { 54 | return upper; 55 | } 56 | 57 | @Override 58 | public Type[] getLowerBounds() { 59 | return lower; 60 | } 61 | 62 | @Override 63 | public String toString() { 64 | if (upper.length > 0) { 65 | if (upper[0] == Object.class) { 66 | return "?"; 67 | } 68 | return getTypeString("? extends ", upper); 69 | } else { 70 | return getTypeString("? super ", lower); 71 | } 72 | } 73 | 74 | private String getTypeString(String prefix, Class[] type) { 75 | StringBuilder sb = new StringBuilder(); 76 | sb.append(prefix); 77 | 78 | for (int i = 0; i < type.length; i++) { 79 | if (i != 0) { 80 | sb.append(" & "); 81 | } 82 | sb.append(type[i].getName()); 83 | } 84 | 85 | return sb.toString(); 86 | 87 | } 88 | 89 | @Override 90 | public boolean equals(Object o) { 91 | if (this == o) return true; 92 | if (o == null || getClass() != o.getClass()) return false; 93 | 94 | WildcardTypeImpl that = (WildcardTypeImpl) o; 95 | 96 | return Arrays.equals(upper, that.upper) && Arrays.equals(lower, that.lower); 97 | 98 | } 99 | 100 | @Override 101 | public int hashCode() { 102 | int result = Arrays.hashCode(upper); 103 | result = 31 * result + Arrays.hashCode(lower); 104 | return result; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=8883 -------------------------------------------------------------------------------- /src/test/java/cn/wildfirechat/app/ApplicationTests.java: -------------------------------------------------------------------------------- 1 | package cn.wildfirechat.app; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class ApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | --------------------------------------------------------------------------------