commit
e3eb5d9413
18 changed files with 1344 additions and 0 deletions
@ -0,0 +1,137 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
||||||
|
<project basedir="." default="jar" name="plugin"> |
||||||
|
<!-- JDK路径,根据自己机器上实际位置修改--> |
||||||
|
<property name="jdk.home" value="/Users/hujian/software/jdk1.8.0_211.jdk/Contents/Home"/> |
||||||
|
<property name="libs" value="${basedir}/lib"/> |
||||||
|
<property name="dependenceLibs" value="${basedir}/dependence"/> |
||||||
|
<property name="FRLibs" value="${basedir}/../../webroot/WEB-INF/lib"/> |
||||||
|
|
||||||
|
<property name="destLoc" value="."/> |
||||||
|
<property name="classes" value="classes"/> |
||||||
|
<xmlproperty file="${basedir}/plugin.xml"/> |
||||||
|
<property name="current-version" value="${plugin.version}"/> |
||||||
|
<property name="current-id" value="${plugin.id}"/> |
||||||
|
|
||||||
|
<!-- 插件版本--> |
||||||
|
<property name="plugin-version" value="${current-version}"/> |
||||||
|
<!-- 插件名字--> |
||||||
|
<property name="plugin-name" value="webhook"/> |
||||||
|
<property name="plugin-jar" value="plugin-${plugin-name}-${plugin-version}.jar"/> |
||||||
|
<target name="prepare"> |
||||||
|
<delete dir="${classes}"/> |
||||||
|
</target> |
||||||
|
<path id="compile.classpath"> |
||||||
|
<fileset dir="${FRLibs}"> |
||||||
|
<include name="**/*.jar"/> |
||||||
|
</fileset> |
||||||
|
<fileset dir="${libs}"> |
||||||
|
<include name="**/*.jar"/> |
||||||
|
</fileset> |
||||||
|
<fileset dir="${dependenceLibs}"> |
||||||
|
<include name="**/*.jar"/> |
||||||
|
</fileset> |
||||||
|
</path> |
||||||
|
<patternset id="resources4Jar"> |
||||||
|
<exclude name="**/.settings/**"/> |
||||||
|
<exclude name=".classpath"/> |
||||||
|
<exclude name=".project"/> |
||||||
|
|
||||||
|
<exclude name="**/*.java"/> |
||||||
|
<exclude name="**/*.db"/> |
||||||
|
<exclude name="**/*.g"/> |
||||||
|
<exclude name="**/package.html"/> |
||||||
|
</patternset> |
||||||
|
<target name="copy_resources"> |
||||||
|
<echo message="从${resources_from}拷贝图片,JS,CSS等资源文件"/> |
||||||
|
<delete dir="tmp"/> |
||||||
|
<copy todir="tmp"> |
||||||
|
<fileset dir="${resources_from}\src\main\java"> |
||||||
|
<patternset refid="resources4Jar"/> |
||||||
|
</fileset> |
||||||
|
</copy> |
||||||
|
<copy todir="tmp"> |
||||||
|
<fileset dir="${resources_from}\src\main\resources"> |
||||||
|
<patternset refid="resources4Jar"/> |
||||||
|
</fileset> |
||||||
|
</copy> |
||||||
|
<copy todir="${classes}"> |
||||||
|
<fileset dir="tmp"/> |
||||||
|
</copy> |
||||||
|
<delete dir="tmp"/> |
||||||
|
</target> |
||||||
|
<target name="compile_javas"> |
||||||
|
<echo message="编译${compile_files}下的Java文件"/> |
||||||
|
<javac destdir="${classes}" debug="false" optimize="on" source="${source_jdk_version}" |
||||||
|
target="${target_jdk_version}" |
||||||
|
fork="true" memoryMaximumSize="512m" listfiles="false" srcdir="${basedir}" |
||||||
|
executable="${compile_jdk_version}/bin/javac" includeantruntime="on"> |
||||||
|
<src path="${basedir}/src"/> |
||||||
|
<exclude name="**/.svn/**"/> |
||||||
|
<compilerarg line="-encoding UTF8 "/> |
||||||
|
<classpath refid="compile.classpath"/> |
||||||
|
</javac> |
||||||
|
<taskdef name="pretreatment" classname="com.fr.plugin.pack.PluginPretreatmentTask"> |
||||||
|
<classpath refid="compile.classpath"/> |
||||||
|
</taskdef> |
||||||
|
<pretreatment baseDir="${basedir}"/> |
||||||
|
</target> |
||||||
|
|
||||||
|
<target name="jar_classes"> |
||||||
|
<echo message="打Jar包:${jar_name}"/> |
||||||
|
<delete file="${basedir}/${jar_name}"/> |
||||||
|
<jar jarfile="${basedir}/${jar_name}"> |
||||||
|
<fileset dir="${classes}"> |
||||||
|
</fileset> |
||||||
|
</jar> |
||||||
|
</target> |
||||||
|
|
||||||
|
<target name="super_jar" depends="prepare"> |
||||||
|
<antcall target="copy_resources"> |
||||||
|
<param name="resources_from" value="${basedir}"/> |
||||||
|
</antcall> |
||||||
|
<antcall target="compile_javas"> |
||||||
|
<param name="source_jdk_version" value="1.8"/> |
||||||
|
<param name="target_jdk_version" value="1.8"/> |
||||||
|
<param name="compile_jdk_version" value="${jdk.home}"/> |
||||||
|
<param name="compile_files" value="${basedir}/src"/> |
||||||
|
</antcall> |
||||||
|
<echo message="compile plugin success!"/> |
||||||
|
|
||||||
|
<antcall target="jar_classes"> |
||||||
|
<param name="jar_name" value="${plugin-jar}"/> |
||||||
|
</antcall> |
||||||
|
<delete dir="${classes}"/> |
||||||
|
</target> |
||||||
|
|
||||||
|
<target name="jar" depends="super_jar"> |
||||||
|
<antcall target="zip"/> |
||||||
|
</target> |
||||||
|
|
||||||
|
<target name="zip"> |
||||||
|
<property name="plugin-folder" value="fr-plugin-${plugin-name}-${plugin-version}"/> |
||||||
|
<echo message="----------zip files----------"/> |
||||||
|
<mkdir dir="${plugin-folder}"/> |
||||||
|
<copy todir="${plugin-folder}"> |
||||||
|
<fileset dir="."> |
||||||
|
<include name="*.jar"/> |
||||||
|
<include name="plugin.xml"/> |
||||||
|
</fileset> |
||||||
|
</copy> |
||||||
|
<copy todir="${plugin-folder}"> |
||||||
|
<fileset dir="${libs}"> |
||||||
|
<include name="**/*.jar"/> |
||||||
|
</fileset> |
||||||
|
</copy> |
||||||
|
<zip destfile="${basedir}/${plugin-folder}.zip" basedir="."> |
||||||
|
<include name="${plugin-folder}/*.jar"/> |
||||||
|
<include name="${plugin-folder}/plugin.xml"/> |
||||||
|
</zip> |
||||||
|
<xmlproperty file="${basedir}/plugin.xml"/> |
||||||
|
<!-- |
||||||
|
<move file="${plugin-folder}.zip" todir="${destLoc}/${plugin.name}"/> |
||||||
|
--> |
||||||
|
<delete dir="${plugin-folder}"/> |
||||||
|
<delete file="${plugin-jar}"/> |
||||||
|
<!--<delete file="${basedir}/${plugin-folder}.zip" />--> |
||||||
|
</target> |
||||||
|
</project> |
@ -0,0 +1,33 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?><plugin> |
||||||
|
<id>com.fr.plugin.dingding.webhook</id> |
||||||
|
<name><![CDATA[钉钉webhook]]></name> |
||||||
|
<active>yes</active> |
||||||
|
<version>1.11</version> |
||||||
|
<env-version>10.0</env-version> |
||||||
|
<jartime>2018-07-31</jartime> |
||||||
|
<vendor>fr.open</vendor> |
||||||
|
<description><![CDATA[钉钉webhook]]></description> |
||||||
|
<change-notes><![CDATA[ |
||||||
|
[2021-09-06]【1.0】初始化插件<br/> |
||||||
|
[2021-09-14]【1.1】重新打包<br/> |
||||||
|
[2021-09-15]【1.2】增加定时调度链接传参<br/> |
||||||
|
[2021-09-15]【1.3】增加获取默认图片<br/> |
||||||
|
[2021-09-15]【1.4】增加授权和增加获取ticket的函数<br/> |
||||||
|
[2021-09-28]【1.5】增加webhook默认图片选择<br/> |
||||||
|
[2021-09-28]【1.6】增加webhook默认图片选择<br/> |
||||||
|
[2022-03-01]【1.7】默认封面为系统生成的图片<br/> |
||||||
|
[2022-03-02]【1.8】兼容jpg图片生成<br/> |
||||||
|
[2022-03-08]【1.9】npe问题修改<br/> |
||||||
|
[2022-03-08]【1.10】使用自带导出的png<br/> |
||||||
|
[2022-03-18]【1.11】增加结果用户配置项<br/> |
||||||
|
]]></change-notes> |
||||||
|
<lifecycle-monitor class="com.fr.plugin.dingding.webhook.OutputPluginLifecycleMonitor"/> |
||||||
|
<extra-core> |
||||||
|
<FunctionDefineProvider class="com.fr.plugin.dingding.webhook.fun.TicketFun" name="GetTableauTicket" description="获取ticket的函数。"/> |
||||||
|
</extra-core> |
||||||
|
<extra-decision> |
||||||
|
<WebResourceProvider class="com.fr.plugin.dingding.webhook.js.JSCSSBridge"/> |
||||||
|
<DecisionDBAccessProvider class="com.fr.plugin.dingding.webhook.OutputDBAccess"/> |
||||||
|
</extra-decision> |
||||||
|
<function-recorder class="com.fr.plugin.dingding.webhook.js.JSCSSBridge"/> |
||||||
|
</plugin> |
@ -0,0 +1,6 @@ |
|||||||
|
# open-JSD-9670 |
||||||
|
|
||||||
|
JSD-9670 将指定报表的截图发送到指定钉钉群里\ |
||||||
|
免责说明:该源码为第三方爱好者提供,不保证源码和方案的可靠性,也不提供任何形式的源码教学指导和协助!\ |
||||||
|
仅作为开发者学习参考使用!禁止用于任何商业用途!\ |
||||||
|
为保护开发者隐私,开发者信息已隐去!若原开发者希望公开自己的信息,可联系【pioneer】处理。 |
@ -0,0 +1,43 @@ |
|||||||
|
package com.fr.plugin.dingding.webhook; |
||||||
|
|
||||||
|
import com.fr.decision.plugin.db.AbstractDecisionDBAccessProvider; |
||||||
|
import com.fr.plugin.dingding.webhook.dao.WebHookDao; |
||||||
|
import com.fr.plugin.dingding.webhook.entity.WebHookEntity; |
||||||
|
import com.fr.stable.db.accessor.DBAccessor; |
||||||
|
import com.fr.stable.db.dao.BaseDAO; |
||||||
|
import com.fr.stable.db.dao.DAOProvider; |
||||||
|
|
||||||
|
/** |
||||||
|
* @Author fr.open |
||||||
|
* @Date 2020/9/15 |
||||||
|
* @Description |
||||||
|
**/ |
||||||
|
public class OutputDBAccess extends AbstractDecisionDBAccessProvider { |
||||||
|
|
||||||
|
private static DBAccessor dbAccessor; |
||||||
|
public DBAccessor getDbAccessor() { |
||||||
|
return dbAccessor; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public DAOProvider[] registerDAO() { |
||||||
|
return new DAOProvider[]{ |
||||||
|
new DAOProvider() { |
||||||
|
@Override |
||||||
|
public Class getEntityClass() { |
||||||
|
return WebHookEntity.class; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Class<? extends BaseDAO> getDAOClass() { |
||||||
|
return WebHookDao.class; |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onDBAvailable(DBAccessor dbAccessor) { |
||||||
|
OutputDBAccess.dbAccessor = dbAccessor; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,45 @@ |
|||||||
|
package com.fr.plugin.dingding.webhook; |
||||||
|
|
||||||
|
import com.fr.intelli.record.Focus; |
||||||
|
import com.fr.intelli.record.Original; |
||||||
|
import com.fr.plugin.context.PluginContext; |
||||||
|
import com.fr.plugin.context.PluginContexts; |
||||||
|
import com.fr.plugin.dingding.webhook.entity.OutputWebHook; |
||||||
|
import com.fr.plugin.dingding.webhook.entity.WebHookEntity; |
||||||
|
import com.fr.plugin.dingding.webhook.format.PNGOutputFormat; |
||||||
|
import com.fr.plugin.dingding.webhook.handle.WebHookHandle; |
||||||
|
import com.fr.plugin.observer.inner.AbstractPluginLifecycleMonitor; |
||||||
|
import com.fr.schedule.extension.report.job.output.BaseOutputFormat; |
||||||
|
import com.fr.schedule.feature.ScheduleOutputActionEntityRegister; |
||||||
|
import com.fr.schedule.feature.output.OutputActionHandler; |
||||||
|
import com.fr.stable.fun.Authorize; |
||||||
|
|
||||||
|
/** |
||||||
|
* @Author fr.open |
||||||
|
* @Date 2020/9/15 |
||||||
|
* @Description |
||||||
|
**/ |
||||||
|
@Authorize(callSignKey = PluginConstants.PLUGIN_ID) |
||||||
|
public class OutputPluginLifecycleMonitor extends AbstractPluginLifecycleMonitor { |
||||||
|
@Override |
||||||
|
@Focus(id = PluginConstants.PLUGIN_ID, text = "钉钉webhook", source = Original.PLUGIN) |
||||||
|
public void afterRun(PluginContext pluginContext) { |
||||||
|
if (!PluginContexts.currentContext().isAvailable()) { |
||||||
|
return; |
||||||
|
} |
||||||
|
BaseOutputFormat.registerOutputFormat(new PNGOutputFormat()); |
||||||
|
OutputActionHandler.registerHandler(new WebHookHandle(), OutputWebHook.class.getName()); |
||||||
|
ScheduleOutputActionEntityRegister.getInstance().addClass(WebHookEntity.class); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
@Focus(id = PluginConstants.PLUGIN_ID, text = "钉钉webhook", source = Original.PLUGIN) |
||||||
|
public void beforeStop(PluginContext pluginContext) { |
||||||
|
if (!PluginContexts.currentContext().isAvailable()) { |
||||||
|
return; |
||||||
|
} |
||||||
|
BaseOutputFormat.removeOutputFormat(PNGOutputFormat.CONVERT_TO_PNG); |
||||||
|
OutputActionHandler.removeOutputHandler(OutputWebHook.class.getName()); |
||||||
|
ScheduleOutputActionEntityRegister.getInstance().removeClass(WebHookEntity.class); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
package com.fr.plugin.dingding.webhook; |
||||||
|
|
||||||
|
/** |
||||||
|
* @Author fr.open |
||||||
|
* @Date 2021/3/1 |
||||||
|
* @Description |
||||||
|
**/ |
||||||
|
public class PluginConstants { |
||||||
|
|
||||||
|
public static final String PLUGIN_ID = "com.fr.plugin.dingding.webhook"; |
||||||
|
} |
@ -0,0 +1,21 @@ |
|||||||
|
package com.fr.plugin.dingding.webhook.dao; |
||||||
|
|
||||||
|
import com.fr.plugin.dingding.webhook.entity.WebHookEntity; |
||||||
|
import com.fr.stable.db.dao.BaseDAO; |
||||||
|
import com.fr.stable.db.session.DAOSession; |
||||||
|
|
||||||
|
/** |
||||||
|
* @Author fr.open |
||||||
|
* @Date 2020/9/15 |
||||||
|
* @Description |
||||||
|
**/ |
||||||
|
public class WebHookDao extends BaseDAO<WebHookEntity> { |
||||||
|
public WebHookDao(DAOSession daoSession) { |
||||||
|
super(daoSession); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected Class<WebHookEntity> getEntityClass() { |
||||||
|
return WebHookEntity.class; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,62 @@ |
|||||||
|
package com.fr.plugin.dingding.webhook.entity; |
||||||
|
|
||||||
|
import com.fr.schedule.base.bean.output.BaseOutputAction; |
||||||
|
import com.fr.schedule.base.entity.AbstractScheduleEntity; |
||||||
|
import com.fr.schedule.base.type.RunType; |
||||||
|
import com.fr.third.fasterxml.jackson.annotation.JsonSubTypes; |
||||||
|
|
||||||
|
/** |
||||||
|
* @Author fr.open |
||||||
|
* @Date 2020/9/15 |
||||||
|
* @Description |
||||||
|
**/ |
||||||
|
@JsonSubTypes.Type(value = OutputWebHook.class, name = "OutputWebHook") |
||||||
|
public class OutputWebHook extends BaseOutputAction { |
||||||
|
|
||||||
|
private static final long serialVersionUID = 8921116228585639504L; |
||||||
|
|
||||||
|
private String hookUrl = null; |
||||||
|
|
||||||
|
public OutputWebHook() { |
||||||
|
super(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean willExecuteByUser() { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public RunType runType() { |
||||||
|
return RunType.SEND_FILE; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Class<? extends AbstractScheduleEntity> outputActionEntityClass() { |
||||||
|
return WebHookEntity.class; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public AbstractScheduleEntity createOutputActionEntity() { |
||||||
|
return (new WebHookEntity()).id(this.getId()).hookUrl(this.hookUrl); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public OutputWebHook id(String id) { |
||||||
|
setId(id); |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public String getHookUrl() { |
||||||
|
return hookUrl; |
||||||
|
} |
||||||
|
|
||||||
|
public void setHookUrl(String hookUrl) { |
||||||
|
this.hookUrl = hookUrl; |
||||||
|
} |
||||||
|
|
||||||
|
public OutputWebHook hookUrl(String hookUrl) { |
||||||
|
setHookUrl(hookUrl); |
||||||
|
return this; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,48 @@ |
|||||||
|
package com.fr.plugin.dingding.webhook.entity; |
||||||
|
|
||||||
|
import com.fr.schedule.base.bean.BaseBean; |
||||||
|
import com.fr.schedule.base.entity.AbstractScheduleEntity; |
||||||
|
import com.fr.stable.db.entity.TableAssociation; |
||||||
|
import com.fr.third.javax.persistence.Column; |
||||||
|
import com.fr.third.javax.persistence.Entity; |
||||||
|
import com.fr.third.javax.persistence.Table; |
||||||
|
|
||||||
|
/** |
||||||
|
* @Author fr.open |
||||||
|
* @Date 2020/9/15 |
||||||
|
* @Description |
||||||
|
**/ |
||||||
|
@Entity |
||||||
|
@Table(name = "fine_output_dingding_webHook") //表名
|
||||||
|
@TableAssociation(associated = true) |
||||||
|
public class WebHookEntity extends AbstractScheduleEntity { |
||||||
|
|
||||||
|
@Column(name = "hookUrl") |
||||||
|
private String hookUrl; |
||||||
|
|
||||||
|
public WebHookEntity() { |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public BaseBean createBean() { |
||||||
|
return new OutputWebHook().id(this.getId()).hookUrl(this.hookUrl); |
||||||
|
} |
||||||
|
|
||||||
|
public String getHookUrl() { |
||||||
|
return hookUrl; |
||||||
|
} |
||||||
|
|
||||||
|
public void setHookUrl(String hookUrl) { |
||||||
|
this.hookUrl = hookUrl; |
||||||
|
} |
||||||
|
|
||||||
|
public WebHookEntity hookUrl(String hookUrl) { |
||||||
|
setHookUrl(hookUrl); |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public WebHookEntity id(String id) { |
||||||
|
setId(id); |
||||||
|
return this; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,40 @@ |
|||||||
|
package com.fr.plugin.dingding.webhook.format; |
||||||
|
|
||||||
|
import com.fr.io.exporter.ImageExporter; |
||||||
|
import com.fr.main.workbook.ResultWorkBook; |
||||||
|
import com.fr.schedule.extension.report.job.output.BaseOutputFormat; |
||||||
|
|
||||||
|
import java.io.OutputStream; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* @Author fr.open |
||||||
|
* @Date 2020/9/15 |
||||||
|
* @Description |
||||||
|
**/ |
||||||
|
public class PNGOutputFormat extends BaseOutputFormat { |
||||||
|
public static final int CONVERT_TO_PNG = 64; |
||||||
|
|
||||||
|
public PNGOutputFormat() { |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int getFormat() { |
||||||
|
return CONVERT_TO_PNG; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getFileSuffix() { |
||||||
|
return ".png"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean withParentPath() { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void flushWithParentPath(OutputStream var1, ResultWorkBook var2, String var3, final List<String> var4) throws Exception { |
||||||
|
new ImageExporter("png", 96).export(var1, var2); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,66 @@ |
|||||||
|
package com.fr.plugin.dingding.webhook.fun; |
||||||
|
|
||||||
|
import com.fr.general.http.HttpRequest; |
||||||
|
import com.fr.general.http.HttpToolbox; |
||||||
|
import com.fr.intelli.record.Focus; |
||||||
|
import com.fr.intelli.record.Original; |
||||||
|
import com.fr.log.FineLoggerFactory; |
||||||
|
import com.fr.plugin.context.PluginContexts; |
||||||
|
import com.fr.plugin.dingding.webhook.PluginConstants; |
||||||
|
import com.fr.script.AbstractFunction; |
||||||
|
import com.fr.stable.ArrayUtils; |
||||||
|
import com.fr.stable.Primitive; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
import com.fr.stable.exception.FormulaException; |
||||||
|
import com.fr.stable.fun.Authorize; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
/** |
||||||
|
* @Author fr.open |
||||||
|
* @Date 2021/9/15 |
||||||
|
* @Description |
||||||
|
**/ |
||||||
|
@Authorize(callSignKey = PluginConstants.PLUGIN_ID) |
||||||
|
public class TicketFun extends AbstractFunction { |
||||||
|
@Override |
||||||
|
@Focus(id = PluginConstants.PLUGIN_ID, text = "钉钉webhook", source = Original.PLUGIN) |
||||||
|
public Object run(Object[] args) throws FormulaException { |
||||||
|
if (!PluginContexts.currentContext().isAvailable()) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
int len = ArrayUtils.getLength(args); |
||||||
|
if (len == 0) { |
||||||
|
return Primitive.ERROR_VALUE; |
||||||
|
} |
||||||
|
String user = (String) args[0]; |
||||||
|
String target = (String) args[1]; |
||||||
|
|
||||||
|
if(StringUtils.isBlank(user) || StringUtils.isBlank(target)){ |
||||||
|
return Primitive.ERROR_VALUE; |
||||||
|
} |
||||||
|
String url =StringUtils.EMPTY; |
||||||
|
if(args.length < 3){ |
||||||
|
url = "http://xxxx:xxx/trusted"; |
||||||
|
}else { |
||||||
|
url = (String) args[2]; |
||||||
|
if(StringUtils.isBlank(url)){ |
||||||
|
url = "http://xxx:xxx/trusted"; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
Map<String, String> param = new HashMap<>(); |
||||||
|
param.put("username",user); |
||||||
|
param.put("target_site",target); |
||||||
|
try { |
||||||
|
String execute = HttpToolbox.executeAndParse(HttpRequest.custom().post(param).url(url).build()); |
||||||
|
return execute; |
||||||
|
} catch (IOException e) { |
||||||
|
FineLoggerFactory.getLogger().error(e.getMessage(),e); |
||||||
|
} |
||||||
|
|
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,132 @@ |
|||||||
|
package com.fr.plugin.dingding.webhook.handle; |
||||||
|
|
||||||
|
import com.fr.base.Formula; |
||||||
|
import com.fr.base.PropertiesUtils; |
||||||
|
import com.fr.io.utils.ResourceIOUtils; |
||||||
|
import com.fr.json.JSONObject; |
||||||
|
import com.fr.log.FineLoggerFactory; |
||||||
|
import com.fr.plugin.dingding.webhook.entity.OutputWebHook; |
||||||
|
import com.fr.plugin.dingding.webhook.util.DesECBUtil; |
||||||
|
import com.fr.plugin.dingding.webhook.util.HttpUtil; |
||||||
|
import com.fr.schedule.base.constant.ScheduleConstants; |
||||||
|
import com.fr.schedule.feature.output.OutputActionHandler; |
||||||
|
import com.fr.stable.CodeUtils; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
|
||||||
|
import java.net.URLEncoder; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
/** |
||||||
|
* @Author fr.open |
||||||
|
* @Date 2020/9/15 |
||||||
|
* @Description |
||||||
|
**/ |
||||||
|
public class WebHookHandle extends OutputActionHandler<OutputWebHook> { |
||||||
|
private static final String key = "xxxx"; |
||||||
|
|
||||||
|
private static final String file = "/resources/Robot.png"; |
||||||
|
|
||||||
|
@Override |
||||||
|
public void doAction(OutputWebHook outputWebHook, Map<String, Object> map) throws Exception { |
||||||
|
String[] files = (String[]) map.get(ScheduleConstants.OUTPUT_FILES); |
||||||
|
getUrl(outputWebHook, map); |
||||||
|
String mediaId = StringUtils.EMPTY; |
||||||
|
String imageFile = StringUtils.EMPTY; |
||||||
|
String imgUrl = getParam(map, "ImgUrl"); |
||||||
|
if (files != null) { |
||||||
|
for (String file : files) { |
||||||
|
if (file.endsWith("png")) { |
||||||
|
imageFile = file; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} else if (StringUtils.isNotBlank(imgUrl) && ResourceIOUtils.exist("/resources/" + imgUrl + ".png")) { |
||||||
|
FineLoggerFactory.getLogger().info("read default image {}", imgUrl); |
||||||
|
imageFile = "/resources/" + imgUrl + ".png"; |
||||||
|
} else if (ResourceIOUtils.exist(file)) { |
||||||
|
FineLoggerFactory.getLogger().info("read default image {}", file); |
||||||
|
imageFile = file; |
||||||
|
} |
||||||
|
|
||||||
|
JSONObject object = HttpUtil.uploadMedia(imageFile); |
||||||
|
FineLoggerFactory.getLogger().info("upload media res is {}", object); |
||||||
|
if (HttpUtil.isOk(object)) { |
||||||
|
mediaId = object.getJSONObject("url").getString("media_id"); |
||||||
|
} |
||||||
|
/*if (StringUtils.isBlank(mediaId)) { |
||||||
|
throw new Exception("not contain media or upload failed"); |
||||||
|
}*/ |
||||||
|
String taskName = CodeUtils.encodeURIComponent((String) map.get(ScheduleConstants.TASK_NAME)); |
||||||
|
String path = CodeUtils.encodeURIComponent((String) map.get(ScheduleConstants.SAVE_DIRECTORY)); |
||||||
|
path = path.replaceAll("\\+", "%20"); |
||||||
|
String showType = (String) map.get(ScheduleConstants.SHOW_TYPE); |
||||||
|
int taskType = (Integer) map.get(ScheduleConstants.TASK_TYPE); |
||||||
|
String scheduleUsername = (String) map.get(ScheduleConstants.USERNAME); |
||||||
|
String resultUrl = getParam(map, "resultUrl"); |
||||||
|
String mobileUrl = outputWebHook.getResultURL() + "/url/mobile/schedule/result?taskName=" + taskName + "&username=" + scheduleUsername + "&path=" + path + "&showType=" + showType + "&taskType=" + taskType; |
||||||
|
HttpUtil.sendWebhook(mediaId, outputWebHook.getHookUrl(), getParam(map, "title"), getParam(map, "text"), delaSign(StringUtils.isNotBlank(resultUrl) ? resultUrl : mobileUrl, map)); |
||||||
|
} |
||||||
|
|
||||||
|
private String delaSign(String url, Map<String, Object> map) { |
||||||
|
String path = url; |
||||||
|
try { |
||||||
|
String user = PropertiesUtils.getProperties("dingtalk").getProperty("resultUser"); |
||||||
|
FineLoggerFactory.getLogger().info("get resultUser config is {}", user); |
||||||
|
String resultUser = getParam(map, "resultUser"); |
||||||
|
if (StringUtils.isNotBlank(resultUser)) { |
||||||
|
FineLoggerFactory.getLogger().info("get resultUser config by param is {}", resultUser); |
||||||
|
user = resultUser; |
||||||
|
} |
||||||
|
String encode = URLEncoder.encode(DesECBUtil.encryptDES(user, key), "UTF-8"); |
||||||
|
if (path.indexOf("?") != -1) { |
||||||
|
path += "&result_sign=" + encode; |
||||||
|
} else { |
||||||
|
path += "?result_sign=" + encode; |
||||||
|
} |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||||
|
} |
||||||
|
FineLoggerFactory.getLogger().info("push dingding url is {}", path); |
||||||
|
return path + "&op=h5"; |
||||||
|
} |
||||||
|
|
||||||
|
private String getParam(Map<String, Object> map, String p) { |
||||||
|
List<Map> list = (List) map.get(ScheduleConstants.RECORD_LIST); |
||||||
|
Object title = StringUtils.EMPTY; |
||||||
|
if (list == null || list.isEmpty()) { |
||||||
|
return StringUtils.EMPTY; |
||||||
|
} |
||||||
|
Object param = list.get(0).get(p); |
||||||
|
if (param == null) { |
||||||
|
return StringUtils.EMPTY; |
||||||
|
} |
||||||
|
if (param instanceof Formula) { |
||||||
|
Formula formula = (Formula) param; |
||||||
|
title = formula.getResult(); |
||||||
|
} else { |
||||||
|
title = param.toString(); |
||||||
|
} |
||||||
|
return title.toString(); |
||||||
|
} |
||||||
|
|
||||||
|
private String getUrl(OutputWebHook outputWebHook, Map<String, Object> map) { |
||||||
|
String taskName = CodeUtils.encodeURIComponent((String) map.get(ScheduleConstants.TASK_NAME)); |
||||||
|
String path = CodeUtils.encodeURIComponent((String) map.get(ScheduleConstants.SAVE_DIRECTORY)); |
||||||
|
path = path.replaceAll("\\+", "%20"); |
||||||
|
String showType = (String) map.get(ScheduleConstants.SHOW_TYPE); |
||||||
|
int taskType = (Integer) map.get(ScheduleConstants.TASK_TYPE); |
||||||
|
String scheduleUsername = (String) map.get(ScheduleConstants.USERNAME); |
||||||
|
return outputWebHook.getResultURL() + "/url/mobile/schedule/result?taskName=" + taskName + "&username=" + scheduleUsername + "&path=" + path + "&showType=" + showType + "&taskType=" + taskType; |
||||||
|
} |
||||||
|
|
||||||
|
private JSONObject getJSONObject(String md5, String base) { |
||||||
|
JSONObject obj = JSONObject.create(); |
||||||
|
obj.put("msgtype", "image"); |
||||||
|
JSONObject image = JSONObject.create(); |
||||||
|
image.put("base64", base); |
||||||
|
image.put("md5", md5); |
||||||
|
obj.put("image", image); |
||||||
|
return obj; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,54 @@ |
|||||||
|
package com.fr.plugin.dingding.webhook.js; |
||||||
|
|
||||||
|
import com.fr.plugin.transform.ExecuteFunctionRecord; |
||||||
|
import com.fr.web.struct.Component; |
||||||
|
import com.fr.web.struct.Filter; |
||||||
|
import com.fr.web.struct.browser.RequestClient; |
||||||
|
import com.fr.web.struct.category.ScriptPath; |
||||||
|
import com.fr.web.struct.category.StylePath; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author fr.open |
||||||
|
* @date 2021/9/15 |
||||||
|
*/ |
||||||
|
public class FileDef extends Component { |
||||||
|
public static final FileDef KEY = new FileDef(); |
||||||
|
private FileDef(){} |
||||||
|
/** |
||||||
|
* 返回需要引入的JS脚本路径 |
||||||
|
* @param client 请求客户端描述 |
||||||
|
* @return JS脚本路径 |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public ScriptPath script(RequestClient client ) { |
||||||
|
//如果不需要就直接返回 ScriptPath.EMPTY
|
||||||
|
return ScriptPath.build("com/fr/plugin/dingding/webhook/theme.js"); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 返回需要引入的CSS样式路径 |
||||||
|
* @param client 请求客户端描述 |
||||||
|
* @return CSS样式路径 |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public StylePath style(RequestClient client ) { |
||||||
|
//如果不需要就直接返回 StylePath.EMPTY;
|
||||||
|
return StylePath.EMPTY; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 通过给定的资源过滤器控制是否加载这个资源 |
||||||
|
* @return 资源过滤器 |
||||||
|
*/ |
||||||
|
@ExecuteFunctionRecord |
||||||
|
@Override |
||||||
|
public Filter filter() { |
||||||
|
return new Filter(){ |
||||||
|
@Override |
||||||
|
public boolean accept() { |
||||||
|
//任何情况下我们都在平台组件加载时加载我们的组件
|
||||||
|
return true; |
||||||
|
} |
||||||
|
}; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,25 @@ |
|||||||
|
package com.fr.plugin.dingding.webhook.js; |
||||||
|
|
||||||
|
import com.fr.decision.fun.impl.AbstractWebResourceProvider; |
||||||
|
import com.fr.decision.web.MainComponent; |
||||||
|
import com.fr.plugin.transform.FunctionRecorder; |
||||||
|
import com.fr.web.struct.Atom; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author fr.open |
||||||
|
* @date 2021/9/15 |
||||||
|
*/ |
||||||
|
@FunctionRecorder |
||||||
|
public class JSCSSBridge extends AbstractWebResourceProvider { |
||||||
|
@Override |
||||||
|
public Atom attach() { |
||||||
|
//在平台主组件加载时添加我们自己的组件
|
||||||
|
return MainComponent.KEY; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Atom client() { |
||||||
|
//我们自己要引入的组件
|
||||||
|
return FileDef.KEY; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,66 @@ |
|||||||
|
package com.fr.plugin.dingding.webhook.util; |
||||||
|
|
||||||
|
import com.fr.third.org.apache.commons.codec.binary.Base64; |
||||||
|
|
||||||
|
import javax.crypto.Cipher; |
||||||
|
import javax.crypto.spec.SecretKeySpec; |
||||||
|
import java.security.Key; |
||||||
|
|
||||||
|
/** |
||||||
|
* @Author fr.open |
||||||
|
* @Date 2020/9/15 |
||||||
|
* @Description |
||||||
|
**/ |
||||||
|
public class DesECBUtil { |
||||||
|
/** |
||||||
|
* 加密数据 |
||||||
|
* |
||||||
|
* @param encryptString |
||||||
|
* @param encryptKey |
||||||
|
* @return |
||||||
|
* @throws Exception |
||||||
|
*/ |
||||||
|
public static String encryptDES(String encryptString, String encryptKey) throws Exception { |
||||||
|
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding"); |
||||||
|
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(getKey(encryptKey), "DES")); |
||||||
|
byte[] encryptedData = cipher.doFinal(encryptString.getBytes("UTF-8")); |
||||||
|
return Base64.encodeBase64String(encryptedData); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* key 不足8位补位 |
||||||
|
* |
||||||
|
* @param |
||||||
|
*/ |
||||||
|
public static byte[] getKey(String keyRule) { |
||||||
|
Key key = null; |
||||||
|
byte[] keyByte = keyRule.getBytes(); |
||||||
|
// 创建一个空的八位数组,默认情况下为0
|
||||||
|
byte[] byteTemp = new byte[8]; |
||||||
|
// 将用户指定的规则转换成八位数组
|
||||||
|
for (int i = 0; i < byteTemp.length && i < keyByte.length; i++) { |
||||||
|
byteTemp[i] = keyByte[i]; |
||||||
|
} |
||||||
|
key = new SecretKeySpec(byteTemp, "DES"); |
||||||
|
return key.getEncoded(); |
||||||
|
} |
||||||
|
|
||||||
|
/*** |
||||||
|
* 解密数据 |
||||||
|
* @param decryptString |
||||||
|
* @param decryptKey |
||||||
|
* @return |
||||||
|
* @throws Exception |
||||||
|
*/ |
||||||
|
|
||||||
|
public static String decryptDES(String decryptString, String decryptKey) throws Exception { |
||||||
|
byte[] sourceBytes = Base64.decodeBase64(decryptString); |
||||||
|
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding"); |
||||||
|
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(getKey(decryptKey), "DES")); |
||||||
|
byte[] decoded = cipher.doFinal(sourceBytes); |
||||||
|
return new String(decoded, "UTF-8"); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
@ -0,0 +1,133 @@ |
|||||||
|
package com.fr.plugin.dingding.webhook.util; |
||||||
|
|
||||||
|
import com.fr.general.PropertiesUtils; |
||||||
|
import com.fr.io.utils.ResourceIOUtils; |
||||||
|
import com.fr.json.JSONObject; |
||||||
|
import com.fr.log.FineLoggerFactory; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
import com.fr.third.org.apache.http.NameValuePair; |
||||||
|
import com.fr.third.org.apache.http.client.entity.UrlEncodedFormEntity; |
||||||
|
import com.fr.third.org.apache.http.entity.ContentType; |
||||||
|
import com.fr.third.org.apache.http.entity.mime.HttpMultipartMode; |
||||||
|
import com.fr.third.org.apache.http.entity.mime.MultipartEntityBuilder; |
||||||
|
import com.fr.third.org.apache.http.message.BasicNameValuePair; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.io.InputStream; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
/** |
||||||
|
* @Author fr.open |
||||||
|
* @Date 2020/9/15 |
||||||
|
* @Description |
||||||
|
**/ |
||||||
|
public class HttpUtil { |
||||||
|
|
||||||
|
|
||||||
|
public static JSONObject uploadMedia(String path) { |
||||||
|
JSONObject result = null; |
||||||
|
InputStream fileInputStream = ResourceIOUtils.read(path); |
||||||
|
String fileName = ResourceIOUtils.getName(path); |
||||||
|
// 定时调度图片没有后缀名,用钉钉上传文件接口以type=image的方式传会返回错误,这里伪造一个后缀
|
||||||
|
fileName = addSuffixToScheduleImage(fileName, ".jpg"); |
||||||
|
if (fileInputStream == null || StringUtils.isEmpty(fileName)) { |
||||||
|
FineLoggerFactory.getLogger().warn(String.format("%s路径下未能找到文件!", path)); |
||||||
|
} else { |
||||||
|
try { |
||||||
|
MultipartEntityBuilder builder = MultipartEntityBuilder.create() |
||||||
|
.setMode(HttpMultipartMode.BROWSER_COMPATIBLE) |
||||||
|
.setContentType(ContentType.MULTIPART_FORM_DATA) |
||||||
|
.addBinaryBody("media", ResourceIOUtils.read(path), ContentType.MULTIPART_FORM_DATA, new String(fileName.getBytes("UTF-8"), "ISO_8859_1")); |
||||||
|
Map<String,Object> header = new HashMap(); |
||||||
|
header.put("Content-type", "multipart/form-data"); |
||||||
|
String res = HttpsUtil.doEntityPost(uploadMediaUrl("image"),null,builder.build()); |
||||||
|
result = new JSONObject(res); |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().error(e.getMessage(),e); |
||||||
|
} |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
public static String uploadMediaUrl(String type) { |
||||||
|
return String.format(getBaseUrl() + "/addons/sjwdingtalk/msg/upload?sys_syscode=%s&type=%s", getCode(), type); |
||||||
|
} |
||||||
|
|
||||||
|
private static String getCode() { |
||||||
|
String property = PropertiesUtils.getProperties("dingtalk").getProperty("sys_syscode"); |
||||||
|
return property; |
||||||
|
} |
||||||
|
|
||||||
|
private static String getBaseUrl() { |
||||||
|
String property = PropertiesUtils.getProperties("dingtalk").getProperty("host"); |
||||||
|
return property; |
||||||
|
} |
||||||
|
|
||||||
|
public static String addSuffixToScheduleImage(String fileName, String suffix) { |
||||||
|
if (!StringUtils.contains(fileName, ".")) { |
||||||
|
return fileName + suffix; |
||||||
|
} |
||||||
|
return fileName; |
||||||
|
} |
||||||
|
|
||||||
|
public static boolean isOk(JSONObject result) { |
||||||
|
return result != null && result.optInt("code", -999) |
||||||
|
==1; |
||||||
|
} |
||||||
|
|
||||||
|
public static String sendMessageUrl(String token) { |
||||||
|
return getBaseUrl() + "/addons/sjwdingtalk/msg/send?sys_syscode=" + token; |
||||||
|
} |
||||||
|
|
||||||
|
public static String sendWebhook( String meadia, String hookUrl,String title, String text, String url) throws IOException { |
||||||
|
String path = String.format(getBaseUrl() + "/api/cloudapi/sendrobot?sys_syscode=%s", getCode()); |
||||||
|
|
||||||
|
String result = null; |
||||||
|
try { |
||||||
|
List<NameValuePair> params = new ArrayList(); |
||||||
|
params.add(new BasicNameValuePair("webhook", hookUrl)); |
||||||
|
params.add(new BasicNameValuePair("x_sys_sc", getCode())); |
||||||
|
params.add(new BasicNameValuePair("msgtype", "card")); |
||||||
|
params.add(new BasicNameValuePair("media_id", meadia)); |
||||||
|
params.add(new BasicNameValuePair("title", title)); |
||||||
|
params.add(new BasicNameValuePair("text", text)); |
||||||
|
params.add(new BasicNameValuePair("singleURL", url)); |
||||||
|
UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(params, "UTF-8"); |
||||||
|
Map<String,Object> header = new HashMap(); |
||||||
|
header.put("Content-type", "application/x-www-form-urlencoded"); |
||||||
|
result = HttpsUtil.doEntityPost(path,header,urlEncodedFormEntity); |
||||||
|
FineLoggerFactory.getLogger().info("send webhook result is {}", result); |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||||
|
throw e; |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
public static void getMessage(String msgid) throws Exception { |
||||||
|
List<NameValuePair> params = new ArrayList(); |
||||||
|
params.add(new BasicNameValuePair("msg_id", msgid)); |
||||||
|
UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(params, "UTF-8"); |
||||||
|
Map<String,Object> header = new HashMap(); |
||||||
|
header.put("Content-type", "application/x-www-form-urlencoded"); |
||||||
|
String result = null; |
||||||
|
try { |
||||||
|
result = HttpsUtil.doEntityPost(messageUrl(getCode()),header,urlEncodedFormEntity); |
||||||
|
FineLoggerFactory.getLogger().info("query message result is {}", result); |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||||
|
throw e; |
||||||
|
} |
||||||
|
JSONObject res = new JSONObject(result); |
||||||
|
if (res.getInt("code") == 0) { |
||||||
|
throw new Exception("get message error is" + res.getString("msg")); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static String messageUrl(String token) { |
||||||
|
return getBaseUrl() + "/addons/sjwdingtalk/msg/query?sys_syscode=" + token; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,346 @@ |
|||||||
|
package com.fr.plugin.dingding.webhook.util; |
||||||
|
|
||||||
|
import com.fr.json.JSONObject; |
||||||
|
import com.fr.log.FineLoggerFactory; |
||||||
|
import com.fr.third.org.apache.http.HttpEntity; |
||||||
|
import com.fr.third.org.apache.http.HttpResponse; |
||||||
|
import com.fr.third.org.apache.http.HttpStatus; |
||||||
|
import com.fr.third.org.apache.http.client.HttpClient; |
||||||
|
import com.fr.third.org.apache.http.client.methods.HttpPost; |
||||||
|
import com.fr.third.org.apache.http.config.Registry; |
||||||
|
import com.fr.third.org.apache.http.config.RegistryBuilder; |
||||||
|
import com.fr.third.org.apache.http.conn.socket.ConnectionSocketFactory; |
||||||
|
import com.fr.third.org.apache.http.conn.socket.PlainConnectionSocketFactory; |
||||||
|
import com.fr.third.org.apache.http.conn.ssl.SSLConnectionSocketFactory; |
||||||
|
import com.fr.third.org.apache.http.entity.StringEntity; |
||||||
|
import com.fr.third.org.apache.http.impl.client.HttpClients; |
||||||
|
import com.fr.third.org.apache.http.impl.conn.PoolingHttpClientConnectionManager; |
||||||
|
import com.fr.third.org.apache.http.util.EntityUtils; |
||||||
|
|
||||||
|
import javax.net.ssl.*; |
||||||
|
import java.io.*; |
||||||
|
import java.net.HttpURLConnection; |
||||||
|
import java.net.URL; |
||||||
|
import java.net.URLEncoder; |
||||||
|
import java.security.cert.CertificateException; |
||||||
|
import java.util.Iterator; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.stream.Collectors; |
||||||
|
|
||||||
|
/** |
||||||
|
* @Author fr.open |
||||||
|
* @Date 2020/9/15 |
||||||
|
* @Description |
||||||
|
**/ |
||||||
|
public class HttpsUtil { |
||||||
|
|
||||||
|
private static HostnameVerifier hv = new HostnameVerifier() { |
||||||
|
@Override |
||||||
|
public boolean verify(String urlHostName, SSLSession session) { |
||||||
|
System.out.println("Warning: URL Host: " + urlHostName + " vs. " |
||||||
|
+ session.getPeerHost()); |
||||||
|
return true; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
/** |
||||||
|
* 发送get请求 |
||||||
|
* |
||||||
|
* @param url |
||||||
|
* @param param |
||||||
|
* @param header |
||||||
|
* @return |
||||||
|
* @throws IOException |
||||||
|
*/ |
||||||
|
public static String sendGet(String url, Map<String, String> param, Map<String, String> header) { |
||||||
|
String result = ""; |
||||||
|
BufferedReader in = null; |
||||||
|
String urlNameString = url; |
||||||
|
try { |
||||||
|
if (param != null) { |
||||||
|
urlNameString += "?"; |
||||||
|
urlNameString += param.entrySet() |
||||||
|
.stream() |
||||||
|
.map(entry -> entry.getKey() + "=" + entry.getValue()) |
||||||
|
.collect(Collectors.joining("&")); |
||||||
|
} |
||||||
|
|
||||||
|
URL realUrl = new URL(urlNameString); |
||||||
|
// 打开和URL之间的连接
|
||||||
|
HttpURLConnection connection; |
||||||
|
if (url.startsWith("https")) { |
||||||
|
trustAllHttpsCertificates(); |
||||||
|
HttpsURLConnection.setDefaultHostnameVerifier(hv); |
||||||
|
connection = (HttpURLConnection) realUrl.openConnection(); |
||||||
|
} else { |
||||||
|
connection = (HttpURLConnection) realUrl.openConnection(); |
||||||
|
} |
||||||
|
//设置超时时间
|
||||||
|
connection.setDoInput(true); |
||||||
|
connection.setRequestMethod("GET"); |
||||||
|
connection.setConnectTimeout(5000); |
||||||
|
connection.setReadTimeout(15000); |
||||||
|
// 设置通用的请求属性
|
||||||
|
if (header != null) { |
||||||
|
Iterator<Map.Entry<String, String>> it = header.entrySet().iterator(); |
||||||
|
while (it.hasNext()) { |
||||||
|
Map.Entry<String, String> entry = it.next(); |
||||||
|
System.out.println(entry.getKey() + ":::" + entry.getValue()); |
||||||
|
connection.setRequestProperty(entry.getKey(), entry.getValue()); |
||||||
|
} |
||||||
|
} |
||||||
|
connection.setRequestProperty("accept", "*/*"); |
||||||
|
connection.setRequestProperty("connection", "Keep-Alive"); |
||||||
|
connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); |
||||||
|
// 建立实际的连接
|
||||||
|
connection.connect(); |
||||||
|
// 定义 BufferedReader输入流来读取URL的响应,设置utf8防止中文乱码
|
||||||
|
in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8")); |
||||||
|
String line; |
||||||
|
while ((line = in.readLine()) != null) { |
||||||
|
result += line; |
||||||
|
} |
||||||
|
if (in != null) { |
||||||
|
in.close(); |
||||||
|
} |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().error(e, "get url error ,url is:{},error is {}", urlNameString, e.getMessage()); |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
public static String sendPost(String url, Map<String, Object> header, JSONObject body) { |
||||||
|
PrintWriter out = null; |
||||||
|
BufferedReader in = null; |
||||||
|
String result = null; |
||||||
|
String res = null; |
||||||
|
try { |
||||||
|
String urlNameString = url; |
||||||
|
|
||||||
|
URL realUrl = new URL(urlNameString); |
||||||
|
// 打开和URL之间的连接
|
||||||
|
HttpURLConnection conn; |
||||||
|
if (url.startsWith("https")) { |
||||||
|
trustAllHttpsCertificates(); |
||||||
|
HttpsURLConnection.setDefaultHostnameVerifier(hv); |
||||||
|
conn = (HttpURLConnection) realUrl.openConnection(); |
||||||
|
} else { |
||||||
|
conn = (HttpURLConnection) realUrl.openConnection(); |
||||||
|
} |
||||||
|
// 设置通用的请求属性
|
||||||
|
conn.setRequestProperty("accept", "*/*"); |
||||||
|
conn.setRequestProperty("connection", "Keep-Alive"); |
||||||
|
// conn.setRequestProperty("user-agent",
|
||||||
|
// "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
|
||||||
|
conn.setRequestProperty("Content-Type", "application/json;charset=UTF-8"); |
||||||
|
if (header != null) { |
||||||
|
header.forEach((k, v) -> { |
||||||
|
conn.setRequestProperty(k, String.valueOf(v)); |
||||||
|
}); |
||||||
|
} |
||||||
|
// 发送POST请求必须设置如下两行
|
||||||
|
conn.setDoOutput(true); |
||||||
|
conn.setDoInput(true); |
||||||
|
//获取请求头
|
||||||
|
|
||||||
|
// 获取URLConnection对象对应的输出流
|
||||||
|
out = new PrintWriter(conn.getOutputStream()); |
||||||
|
// 发送请求参数
|
||||||
|
if (body != null) { |
||||||
|
FineLoggerFactory.getLogger().error("content data: {}", body.toString()); |
||||||
|
FineLoggerFactory.getLogger().error("content cover data: {}", new String(body.toString().getBytes("UTF-8"), "UTF-8")); |
||||||
|
out.print(new String(body.toString().getBytes("UTF-8"), "UTF-8")); |
||||||
|
} |
||||||
|
// flush输出流的缓冲
|
||||||
|
out.flush(); |
||||||
|
// 定义BufferedReader输入流来读取URL的响应
|
||||||
|
in = new BufferedReader( |
||||||
|
new InputStreamReader(conn.getInputStream())); |
||||||
|
String line; |
||||||
|
while ((line = in.readLine()) != null) { |
||||||
|
result += line; |
||||||
|
} |
||||||
|
res = result; |
||||||
|
if (res.startsWith("null")) { |
||||||
|
res = res.replace("null", ""); |
||||||
|
} |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||||
|
} |
||||||
|
//使用finally块来关闭输出流、输入流
|
||||||
|
finally { |
||||||
|
try { |
||||||
|
if (out != null) { |
||||||
|
out.close(); |
||||||
|
} |
||||||
|
if (in != null) { |
||||||
|
in.close(); |
||||||
|
} |
||||||
|
} catch (IOException e) { |
||||||
|
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||||
|
} |
||||||
|
} |
||||||
|
return res; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public static String doPost(String url, Map<String, Object> header, JSONObject json) { |
||||||
|
HttpClient client = HttpClients.createDefault(); |
||||||
|
if (url.startsWith("https")) { |
||||||
|
SSLContext sslcontext = createIgnoreVerifySSL(); |
||||||
|
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create() |
||||||
|
.register("http", PlainConnectionSocketFactory.INSTANCE) |
||||||
|
.register("https", new SSLConnectionSocketFactory(sslcontext)) |
||||||
|
.build(); |
||||||
|
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry); |
||||||
|
HttpClients.custom().setConnectionManager(connManager); |
||||||
|
client = HttpClients.custom().setConnectionManager(connManager).build(); |
||||||
|
} |
||||||
|
HttpPost post = new HttpPost(url); |
||||||
|
post.setHeader("accept", "*/*"); |
||||||
|
post.setHeader("connection", "Keep-Alive"); |
||||||
|
post.setHeader("Content-Type", "application/json"); |
||||||
|
if (header != null) { |
||||||
|
header.forEach((k, v) -> { |
||||||
|
post.setHeader(k, String.valueOf(v)); |
||||||
|
}); |
||||||
|
} |
||||||
|
try { |
||||||
|
StringEntity s = new StringEntity(json.toString(),"UTF-8"); |
||||||
|
s.setContentEncoding("UTF-8"); |
||||||
|
s.setContentType("application/json; charset=UTF-8");//发送json数据需要设置contentType
|
||||||
|
post.setEntity(s); |
||||||
|
HttpResponse res = client.execute(post); |
||||||
|
if (res.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { |
||||||
|
String result = EntityUtils.toString(res.getEntity());// 返回json格式:
|
||||||
|
return result; |
||||||
|
} |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().error(e.getMessage(),e); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public static String doEntityPost(String url, Map<String, Object> header, HttpEntity entity) { |
||||||
|
HttpClient client = HttpClients.createDefault(); |
||||||
|
if (url.startsWith("https")) { |
||||||
|
SSLContext sslcontext = createIgnoreVerifySSL(); |
||||||
|
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create() |
||||||
|
.register("http", PlainConnectionSocketFactory.INSTANCE) |
||||||
|
.register("https", new SSLConnectionSocketFactory(sslcontext)) |
||||||
|
.build(); |
||||||
|
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry); |
||||||
|
HttpClients.custom().setConnectionManager(connManager); |
||||||
|
client = HttpClients.custom().setConnectionManager(connManager).build(); |
||||||
|
} |
||||||
|
HttpPost post = new HttpPost(url); |
||||||
|
post.setHeader("accept", "*/*"); |
||||||
|
post.setHeader("connection", "Keep-Alive"); |
||||||
|
if (header != null) { |
||||||
|
header.forEach((k, v) -> { |
||||||
|
post.setHeader(k, String.valueOf(v)); |
||||||
|
}); |
||||||
|
} |
||||||
|
try { |
||||||
|
post.setEntity(entity); |
||||||
|
HttpResponse res = client.execute(post); |
||||||
|
if (res.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { |
||||||
|
String result = EntityUtils.toString(res.getEntity());// 返回json格式:
|
||||||
|
return result; |
||||||
|
} |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().error(e.getMessage(),e); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
private static void trustAllHttpsCertificates() throws Exception { |
||||||
|
TrustManager[] trustAllCerts = new TrustManager[1]; |
||||||
|
TrustManager tm = new miTM(); |
||||||
|
trustAllCerts[0] = tm; |
||||||
|
SSLContext sc = SSLContext.getInstance("SSL", "SunJSSE"); |
||||||
|
sc.init(null, trustAllCerts, null); |
||||||
|
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* encode url by UTF-8 |
||||||
|
* |
||||||
|
* @param url url before encoding |
||||||
|
* @return url after encoding |
||||||
|
*/ |
||||||
|
public static String encodeUrl(String url) { |
||||||
|
String eurl = url; |
||||||
|
try { |
||||||
|
eurl = URLEncoder.encode(url, "UTF-8"); |
||||||
|
} catch (UnsupportedEncodingException e) { |
||||||
|
} |
||||||
|
return eurl; |
||||||
|
} |
||||||
|
|
||||||
|
private static class miTM implements TrustManager, |
||||||
|
X509TrustManager { |
||||||
|
@Override |
||||||
|
public java.security.cert.X509Certificate[] getAcceptedIssuers() { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isServerTrusted( |
||||||
|
java.security.cert.X509Certificate[] certs) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isClientTrusted( |
||||||
|
java.security.cert.X509Certificate[] certs) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void checkServerTrusted( |
||||||
|
java.security.cert.X509Certificate[] certs, String authType) |
||||||
|
throws CertificateException { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void checkClientTrusted( |
||||||
|
java.security.cert.X509Certificate[] certs, String authType) |
||||||
|
throws CertificateException { |
||||||
|
return; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static SSLContext createIgnoreVerifySSL() { |
||||||
|
try { |
||||||
|
SSLContext sc = SSLContext.getInstance("SSLv3"); |
||||||
|
|
||||||
|
// 实现一个X509TrustManager接口,用于绕过验证,不用修改里面的方法
|
||||||
|
X509TrustManager trustManager = new X509TrustManager() { |
||||||
|
@Override |
||||||
|
public void checkClientTrusted( |
||||||
|
java.security.cert.X509Certificate[] paramArrayOfX509Certificate, |
||||||
|
String paramString) throws CertificateException { |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void checkServerTrusted( |
||||||
|
java.security.cert.X509Certificate[] paramArrayOfX509Certificate, |
||||||
|
String paramString) throws CertificateException { |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public java.security.cert.X509Certificate[] getAcceptedIssuers() { |
||||||
|
return null; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
sc.init(null, new TrustManager[]{trustManager}, null); |
||||||
|
return sc; |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,76 @@ |
|||||||
|
!(function () { |
||||||
|
BI.config("dec.provider.schedule", function (provider) { |
||||||
|
provider.registerTaskAttached({ |
||||||
|
value: 64, |
||||||
|
text: "png" |
||||||
|
}, [DecCst.Schedule.TaskType.REPORT, DecCst.Schedule.TaskType.BI]); |
||||||
|
}); |
||||||
|
|
||||||
|
var Plugin = BI.inherit(BI.Widget, { |
||||||
|
props: { |
||||||
|
baseCls: "", |
||||||
|
value: { |
||||||
|
hookUrl: null, |
||||||
|
} |
||||||
|
}, |
||||||
|
render: function () { |
||||||
|
var t = this, |
||||||
|
e = this.options.value[0]==undefined?{hookUrl: null}: this.options.value[0]; |
||||||
|
return { |
||||||
|
type: "bi.flex_vertical", |
||||||
|
tgap: 15, |
||||||
|
items: [{ |
||||||
|
type: "dec.label.editor.item", |
||||||
|
errorTop: 16, |
||||||
|
textCls: "dec-font-weight-bold", |
||||||
|
text: "webHookUrl", |
||||||
|
textWidth: 115, |
||||||
|
editorWidth: 300, |
||||||
|
value: e.hookUrl, |
||||||
|
ref: function(e) { |
||||||
|
t.hookUrl = e |
||||||
|
} |
||||||
|
}] |
||||||
|
}; |
||||||
|
}, |
||||||
|
/** |
||||||
|
* |
||||||
|
* |
||||||
|
* @returns {boolean} |
||||||
|
*/ |
||||||
|
validation: function () { |
||||||
|
var e = !0, |
||||||
|
t = this.isVisible(); |
||||||
|
return BI.isEmpty(this.hookUrl.getValue()) && (t && this.hookUrl.showError(BI.i18nText("Dec-Error_Null")), e = !1), |
||||||
|
e |
||||||
|
}, |
||||||
|
/** |
||||||
|
* |
||||||
|
* outputActionList |
||||||
|
* @returns {{}} |
||||||
|
*/ |
||||||
|
getValue: function() { |
||||||
|
var _self= this; |
||||||
|
return {OutputWebHook: BI.extend(_self.value,{ |
||||||
|
"@class": "com.fr.plugin.dingding.webhook.entity.OutputWebHook", |
||||||
|
actionName: "com.fr.plugin.dingding.webhook.entity.OutputWebHook", |
||||||
|
hookUrl: _self.hookUrl.getValue(), |
||||||
|
})} |
||||||
|
}, |
||||||
|
}); |
||||||
|
BI.shortcut("dec.schedule.task.file.handling.plugin", Plugin); |
||||||
|
|
||||||
|
BI.config("dec.provider.schedule", function (provider) { |
||||||
|
provider.registerHandingWay({ |
||||||
|
text: "webHook", |
||||||
|
value: "com.fr.plugin.dingding.webhook.entity.OutputWebHook", // actionName
|
||||||
|
cardType: "dec.schedule.task.file.handling.plugin", |
||||||
|
actions: [] // action
|
||||||
|
}, [DecCst.Schedule.TaskType.DEFAULT, DecCst.Schedule.TaskType.REPORT, DecCst.Schedule.TaskType.BI]); |
||||||
|
}); |
||||||
|
}()); |
||||||
|
|
||||||
|
BI.Plugin.config(function (type, options) { |
||||||
|
}, function (type, object) { |
||||||
|
object.element.attr("shortcut", object.options.type); |
||||||
|
}); |
Loading…
Reference in new issue