Dooray! > Messenger > slash command 介绍 联动服务 在Dooray messenger中可以用命令语句的方式接收信息,并提高业务效率。想实现messenger中未提供的功能时,可以使用此功能并结合自己的业务,高效率的自动化完成业务。
要介绍的功能是如何使用command,以后会支持对bot、API等多样的联动服务。
slash command slash command是在/后面加字母的方式实现特定功能的命令语句。Dooray messenger提供 /mute, /status, /search 等基本语句。比如,查询信息内容,变更自己的状态等功能,在不使用鼠标点击情况下,通过命令快速实现。
还可以通过自定义命令,来完成自己想要的功能。比如,每天早上接收交通情况、天气预报,通过输入简单的命名生成投票功能。
下图是command 服务和messenger服务的通信过程
用户输入 /文字和对话窗登记过的command。输入的command通过messenger服务传输到command 服务。command 服务中把处理结果返回到messenger服务。messenger服务是通过command 服务返回的数据展示给用户。
使用环境 用户可以在pc和手机中输入command确认返回结果。所以,命令制作者需要考虑手机环境下的layout。目前只对pc支持自定义命令功能。
制作介绍 关于command命令的制作、登记,在以下文档中介绍。
添加command命令 为了使用自定义command命令,需添加Dooray messenger。
移动到添加页面 Dooray messenger的左上方点击自己的名字选择 ‘联动服务’。
和下面一样,显示空画面。
app 添加 首先制作app。app是联动服务的捆扎单位。可以在一个app中添加多个command。输入下面的信息,制作app。各信息会在登记command时,显示在目录中。 구분 설명 Image 在对话窗中使用command时显示成传输者的icon。 Name 在对话窗中使用command时显示成传输者的姓名。 Description app的介绍。 app创建成功。可以看见token和空的内容。token会在command请求时一同传送,参与请求验证。请注意不要泄漏token。如果token泄漏,请通过’Regenerate’ 按钮重新发放token。
添加command 登记app后,点击slash command ‘添加’按钮。建议在一个app中添加密切相关的command。
上一篇文章介绍了项目中测试代码的写法。
Go项目的测试代码2(项目运用)
这里简单的共享一下测试替身。
当我们写测试代码的时候,经常遇到一个问题。
跟别的模块或服务有依赖性,可是功能还没开发完。
或是因为各种原因(安全,白名单,内网等等…)开发环境里无法调用相应的模块。
这时候我们应该如何去写测试代码?
因此测试替身Test Double出现了。 其功能和名字一样,做替身。
测试替身Test Double的分以下类型。 Dummy, Stub, Fake, Spy, Mock
Dummy 最简单、最原始的测试替身型别。Dummy 没有实作,最常用于需要参数值但不使用它的情况。
Null 可视为是 Dummy,但真的 Dummy 是接口或基类的衍生,且完全不包含实作。
Stub Dummy 的上一级,Stub 是接口或基类的最低限度实作。
会传回 Void 的方法通常完全不包含实作,而会传回值的方法通常会传回硬式编码的值。
Spy 测试 Spy 类似 Stub,但除了提供客户端可叫用成员的实例,
Spy 还会记录叫用了哪些成员,好让单元测试验证所叫用的成员是否符合预期。
Fake Fake 包含更复杂的实作,通常涉及所继承型别之不同成员之间的互动。
虽然不是完整的生产实作,但 Fake 与生产实作很相似,尽管它会采取一些快捷方式。
Mock Mock 是由 Mock 链接库动态建立 (其他通常是由测试开发人员使用程序代码来产生)。
测试开发人员永远看不到实作接口或基类的实际程序代码,但是可以设定 Mock 以提供传回值、预期要叫用的特定成员…等等。
视其中的设定而定,Mock 的行为可能会像 Dummy、Stub 或 Spy。
上面是网上流行的概念和理论。
我在项目中的运用 我开发的是在企业微信中的应用,所以需要调用企业微信的API,
用过的人应该知道,这需要登记可信域名(简单的说不能本地用,只能发布到服务器才能调用)。
也可以用第三方工具去模拟调试,但是这么做感觉很不方便。而且Debug也相当麻烦。
我是这么处理的。
项目初期(一阶段) 直接写硬代码hardcode。
一般我们都会说尽量避免写硬代码hardcode,
但是项目初期我建议大家这么写。
我们经常听到数字证书,数字签名这些词。
这些证书,签名到底是什么?
他们又起到什么样的作用? 其原理是什么?
了解这些我们需要先了解加密方式,以及什么是公钥?什么是私钥?
1. 加密方式 先解释一下2种常用的加密方式。
◆ 对称加密
加密的传统方法是对称加密。发出讯息者用一把钥匙对讯息加密。
接收讯息者需用这把钥匙将加密了的讯息解密。
这把钥匙必须以一种其他人没有机会得到它的方式给予接收讯息者。
如果其他人得到了这把钥匙,这种加密方式就没用了。
◆ 非对称加密算法
非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)
公开密钥与私有密钥是一对,可以相互加密和解密。
如果用公钥对数据进行加密,只有用对应的密钥才能解密。
如果用密钥对数据进行加密,那么只有用对应的公钥才能解密。
因为非对称加密算法安全性比较高,所以下面的数字签名,数字证书都是用了非对称加密算法。
2. 数字签名digital signature 在现实生活中,签名是为了表示这是签名者写的。计算机中,数字签名也是相同的含义。
举一个例子如果A,B两台计算机相互通讯:
A计算机传输给B计算机信息的时候,A计算机会在消息的最后写上去自己的签名,以代表这些信息是A计算机的。 B计算机接到消息后,先看签名是不是A计算机判断不是别人冒充A计算机发送不安全或是无效的信息(有效性)。 除此之外,数字签名还能证明消息传输过程中没有被篡改(完整性)。
◆ 原理
简单的说的话其实就是:
A计算机给B计算机传输信息的时候,
A计算机在信息后面加自己的签名(字符串),用自己的私钥(privatekey)加密。
B计算机接到数据后,用A计算机的公钥(publickey)解密,确认来源是不是A计算机。
这样确保了完整性,而且A计算机也不可抵赖
(因为用A计算机公钥解密的信息只能是A计算机的私钥加密的信息)
3. 数字证书 先预想一个场景,如果有10台计算机,10台计算机需要记住相互之间的公钥(publickey),
那有100台计算机,1000台呢? 他们之间都需要记住相互的公钥吗?
答案肯定是不能,那如何解决这些问题呢?
其实很简单,有个第三方中介机构。记住了这些1000台的公钥相对应的资料。
这种机构称为认证机构(Certification Authority, CA)。
CA开一个证明这是计算机A的信息,发给B计算机。
B计算机通过CA的证明,可以确认这是A计算机的信息。
◆ 如何生成证书?
A计算机将自己的【公钥A】给CA
CA用自己的【私钥CA】给【公钥A】加密,生成【数字签名A】
CA把【公钥A】,【数字签名A】,附加一些【A计算机的信息】整合在一起,生成证书,发给A计算机。
◆ 如何验证证书?
A计算机发信息给B计算机的时候,会附加【数字签名A】
B计算机通过CA的公钥解密【数字签名A】,既可以确认这是A计算机发的信息。
(其实详细原理不是这样,是解证书得到哈希值,通过算法比较这个哈希值的。)
总结 两台计算机相互通讯的时候,为了确保有效性和完整性。需要签名证明是自己(数字签名)。
这签名不能随便公开,所以需要加密。
加密的时候使用的是非对称加密算法。(公钥,私钥)
相互通讯的计算机多了后,需要一个中介公司来证明这个签名是合法的(数字证书)。
这中介机构叫(Certification Authority, CA)。
上一篇文章介绍了最基本的测试代码的写法。
Go项目的测试代码1(基础)
这里简单的共享一下我在项目中使用的方式。
项目结构 我们实际项目中, 结构简单地分了控制层controllers和模块层modles
因为现在都已微服务的形式开发,没必要太复杂的结构。
分控制层和模块层已经能满足我们的需求,不需要再细分了。
|___config ||==> 配置文件 | |___config.qa.go | |___config.production.go ... ... |___controllers ||==> 控制层,只做参数的有效性和简单的逻辑处理 | |___app_api_test.go | |___app_api.go | |___init_test.go | |___tenant_api.go ... ... |___models ||==> 模块层,所有的业务都是在模块层里实现的 | |___app.go | |___app_test.go | |___init_test.go | |___tenant.go ... ... |___main.go ||==> 系统的入口 |___factory ||| |___kit ||| ==> 按需求自定义建立一个package方便使用 |___filters ||| ... ... 看项目结构的话,可以发现测试方法直接写在对应的package里面。
有些人喜欢把测试方法分另一个package里写,也可以~ 不同人有不同的喜好。 我也试过这种方式,但是还是喜欢写在同一个package里面,这么写简单方便。
控制层controllers和模块层modles的不同方式 控制层controllers
控制层是提供接口api的直接入口,所以那些重要的api都需要写测试方法。
我喜欢在这里写参数验证,业务验证等等主要功能的测试。
最近写了测试代码,整理了一下。
先看看简单的测试代码
// add_test.go ==> 文件名 _test.go 结尾的默认为测试代码文件 package models import ( "testing" ) //Test开头的默认为测试方法 func TestAdd(t *testing.T) { //arrange var x, y, res int x = 2 y = 3 //act result = Add(x, y) //assert if result != 5 { t.Fatal("Add的结果不正确") } } // add.go package models func Add(x, y int) int { return x + y } 查看测试结构。
$ go test -v ==> 依次运行当前package的 _test.
以前开发的时候都是用本地的sqlite开发,但是极少数情况下,sqlite支持的语法发布到服务器上链接mysql会报错。
为了避免这种现象,还是链接本地mysql开发还是更稳定的, 可是开发的项目多了后,本地的mysql库看起来好乱。 而且有很多项目是实验性的项目,没有及时处理的话会产生很多垃圾数据。
要不使用docker运行mysql,开发结束后把容器删掉 ? 前提是需要准备测试数据脚本,开发或测试的时候随时可以删除,添加数据。 这样就不会因为删除docker容器,重新添加数据而烦恼。 做测试数据很麻烦~ 但是写测试代码,这些测试数据脚本也是必要的。 废话有点多了,说说如何去做。来点干货…^^
1. 安装docker (建议上官网下载安装包安装。)
$ brew install docker 2. 下载mysql镜像
$ docker pull mysql 3. 启动mysql实例
$ docker run --name mingxie-mysql -p 32xxx:3306 -e MYSQL_ROOT_PASSWORD=1234 -d mysql:latest —name 后面的是docker容器名 -p 32xxx:3306 这里需要注意 32xxx 是你链接mysql的时候的Port。 -e MYSQL_ROOT_PASSWORD 是设置mysql的root账号密码 -d mysql 是你的镜像标签 4. 在shell中访问mysql
docker exec -it mingxie-mysql bash root@7c289aa0ca95:/# mysql -uroot -p -h localhost Enter password: 输入密码即可。
Dooray是一个与其它所有工具连接,且简单易懂的业务工具。
GitLab是代码托管的工具(公司自己创建了GitLab网站)。
Dooray也是一个聊天工具,有客户端和web端
-web端地址:https://dooray.com/messenger/orgs
-客户端下载地址:https://dooray.com
1 注册Dooray,GitLab,(Dooray推荐下载载客户端)
2 登陆Dooray账户,并创建业务群。
3 登陆https://pangpang.dooray.com 网站,点击右上脚的纸轮->设置->联动服务。
4 点击添加服务->选择GitLab添加服务。
5 选择要关联的项目和群,复制URL地址,下一步再Gitlab设置中用到。
6 登陆GitLab并创建项目,点击settings->Integrations,填写上面复制的URL,勾选需要的Trigger,并保存。
7 点击test测试。
8 Dooray客户端接收到消息,到这一步就配置成功了~。
9 当你你通过git,push,merge等操作时,Dooray messenger会把信息发给群,群用户可以看到响应信息。
## 代码commit 时输入语句
push commit时message内容输入fix#my-dooray-project/1234 ,my-dooray-project业务的序号1234中会记录push内容。
除了fix还可以用以下的单词。
해결, 완료, fix,fixed, close, closes, closed ressolve, resolves, resolved Dooray的业务内容中所记录内容如下。
这几天研究了用hugo搭建个人博客。
简单的整理了一下。
1.安装hugo(windows 请查看官网介绍 https://gohugo.io/getting-started/installing/)
$ brew install hugo 之后检查版本
$ hugo version Hugo Static Site Generator v0.37.1 darwin/amd64 BuildDate: 2.创建hugo 项目
$ hugo new site my-blog Congratulations! Your new Hugo site is created in /Users/limingxie/Projects/my-blog. Just a few more steps and you're ready to go: 1. Download a theme into the same-named folder. Choose a theme from https://themes.gohugo.io/, or create your own with the "hugo new theme <THEMENAME>" command.
通过1000个代码重构,学习到的知识点 (What I learned from doing 1000 code reviews)(翻译) 在LinkedIn工作的时候,我大部分的工作都是做代码检查。有一些建议不断地反复出现,所以我决定把我和团队分享的清单放在一起。
建议 1: 出错时请抛(throw)出一个异常(exception)
我看到的一个常见的模式是:
List<String> getSearchResults(...) { try { List<String> results = // make REST call to search service return results; } catch (RemoteInvocationException e) { return Collections.emptyList(); } } 这种模式实际上造成了我开发过的移动应用程序的中断。
我们使用的搜索后端开始抛出异常。然而,应用程序的API服务器有一些类似于上面的代码。因此,从应用程序的角度来看,它获得了200的成功响应,并愉快地显示了空列表。
相反,如果API抛出了一个异常,那么我们的监控系统就会立即将其提取出来,并修复。
很多时候,当你遇到异常时,为了便利返回空对象。在java中空对象的例子是Optional.empty(),null,empty list。在解析URL时总是出现这样的问题。如果无法从字符串中解析URL,返回值为null。可以自问:“为什么URL是错误的?”我们应该在上游解决的数据问题吗?“
空对象不是处理这项工作的合适工具。如果发生异常,则应抛出异常。
建议2:尽可能使用具体的类型(type)
这个建议基本上跟stringly typed programming(强类型编程)是相反的。
我经常看到类似这些例子的代码。
void doOperation(String opType, Data data); // where opType is "insert", "append", or "delete", this should have clearly been an enum String fetchWebsite(String url); // where url is "https://google.
Go My Way #2 - DataBase, Logging Jun 14, 2017
Go My Way是介绍我用Go语言开发web应用时首选方案的3篇文章 . 没读过之前的文章,请下面的链接.
Go My Way #1 - web 框架 Go My Way #2 - DataBase, Logging Go My Way #3 - Configuration, Tracing, etc. gomobile 这篇文章介绍数据库和日志
数据库 跟其他语言的ORM(Ruby的active record,.Net的entityframework,Java的JPA,等)相比,Go的DB相关的Package不足之处较多。但是Go社区出现了相关讨论的文章。“什么样的Go ORM 框架优秀? ”的问题(Golang which ORM is better)中,大部分人的意见是提供轻便的query mapper(执行sql语句的返回值绑定到Struct)功能就足够。也有推荐用native query(sql 语句,或者转化成sql语句)开发的文章(Our Go is fine but our SQL is great)。
根据Go社区的趋势判断,不会出现 Active Record或者 Hibernate类似的ORM框架。
本人以前也认为操作DB时应该使用ORM,相比native query,使用ORM提供的抽象化的DSL是更明智的选择。为什么会这么想?应该用面向对象的方式开发代码,觉得用二维的方式操作表是开发水平低下的表现。
应该分开考虑modeling和实际DB处理的方式。定义好模型,基于模型开发项目,DB的处理方式不是很重要。不管你用native query,ORM还是混合使用,找到最佳的方式最重要。一直使用Go语言开发项目,解决问题时相比理论更关注实用性(这才是Go的哲学)。关于ORM,Go社区也一定程度的同意这种观点。(不同意怎么办?想自己开发一个,实力不足,只能适应)。