写在前面
插件实现 Cr. to zxu Jiang。
为什么做这件事?作为大厂搬砖人,每天在各种代码中周转之余,还要处理诸多消息。京me作为京东内部的通讯工具,确实有很多内在提高沟通效率的功能,但你或许还是有这样的体会:每天仍然重复大量的 “1.鼠标点击打开京me - 2.focus在搜索栏 - 3.键盘搜索好友 - 4.选择并发起聊天”。
因此在浅浅调研了下Alfred之后,考虑是否可以自定义开发一个插件,提高京me搜索聊天的效率。最终实现效果可大致理解为Mac的Spotlight Search,省去了很多鼠标操作。键盘键入后可以直接定位某一特定erp的联系人或者群聊并发起聊天,无论你身处哪个页面,都可以一键操作。
注意: 本插件实现及使用目前仅支持MacOs和京东内部员工,但开发思路不受限制。
简介
Alfred介绍
Alfred 是一个用键盘通过热键、关键字、自定义插件来加快操作效率的工具,它不但是搜索工具,还是快速启动工具,甚至能够操作许多系统功能,扩充性极强。简单点说就是使用了 Alfred 后你就可以丢掉鼠标了!
Workflow 是Alfred2.0推出的最激动人心的特性,通过与脚本语言的交互,workflow可以支持任意操作,把日常的重复性事务封装在脚本中,大大的提高工作效率。
Workflow 支持php、bash、perl、ruby以及python(本次所用脚本)作为脚本语言,并内置脚本语言解释器,并通过Stdio的形式在各个脚本模块中传递参数。
在代码中插入{query}块可以接收上一个脚本输出的内容。形成完整的控制链条。 最后由 Alfred 输出至 Output 模块, 在Output模块中, 我们可以启动浏览器、将内容复制到剪切板、 启动通知中心、甚至执行bash脚本。
在日常的使用中,我们通常通过关键字来调用某一模块,例如“find xxx” 即是调用find内建模块,query内容为xxx。 在workflow的开发中, 开发者可以自定义自己编写模块的关键字,只要不与其他模块冲突即可。
在workflow的结构中,数据流通过Alfred的控制线进行传递,每一个脚本模块的Stdio输出会被Alfred替换到下一个脚本的{query}块中。
原理概括
- 第一步通过joyspace的
搜索API搜索京me联系人或者群;
url = "https://apijoyspace.jd.com/v1/search" # api来自joyspace search接口
- 构建alfred要求的返回结果(www.alfredapp.com/help/workfl…);
{"items": [
{
"uid": "desktop",
"type": "file",
"title": "Desktop",
"subtitle": "~/Desktop",
"arg": "~/Desktop",
"autocomplete": "Desktop",
"icon": {
"type": "fileicon",
"path": "~/Desktop"
}
}
]}
- 将对应的员工erp或者群ID带过来,通过京me私有协议将对应的员工聊天框唤起。由于京me是基于
electron开发,electron框架支持唤起应用的私有协议。京me的研发人员开发了唤起员工聊天框和群聊天框的协议,通过私有协议可以直接唤起京me联系人或者群聊天框;
# 唤起协议
员工: timline://chat/?topin={query} # query是员工erp
群聊: timline://chat/?topin={query}&type=2 # query是群聊Id
- 结束
实现思路
1.如何唤起京me并跳转至对应聊天页
最开始注意到这个问题是在京东内部域名下搜索员工erp时,会看到浏览器询问是否允许打开京me,允许后京me将被跳转打开,并直接切换到对应搜索结果的联系人|群聊页面,也是在这里想到用京me的搜索api作为关键去获取构建{query}的参数来实现唤起应用的操作。
mac系统在application中选中京me并点开详情,可以看到它的框架是electron:
因此一通查,知道是electron应用在开发时允许调用私有协议唤起应用,就好比日常中苹果手机用户用Safari浏览器打开某一App是一个道理(一篇比较不错的文章贴在最后参考中)。
通过浏览器抓包可知,唤起应用时需要传入指定参数,也就是上面提到的员工erp和群聊Id,因此,先去构建指定格式的唤起链接:
员工: timline://chat/?topin={query} # query是员工erp
群聊: timline://chat/?topin={query}&type=2 # query是群聊Id
2.使用 Alfred
思路: 利用 Alfred 把流程化的固定步骤使用脚本自动化,在Alfred中搜索出京me好友或群聊并直接发起会话。
这里不再截图展示,可以自行探索Alfred的workflow使用方法,可大致概括为:
Alfred中新建新的workflow,根据要实现的功能选择合适的特性,填写相关信息,写入脚本即可。
Alfred提供了已经封装好的workflow util,可以大大提高写脚本效率。
下方参考链接中贴了一份一位其他大佬利用workflow实现插件的过程。
脚本实现:
# python脚本文件
# encoding: utf-8
import json
import sys
import browser_cookie3
import requests as requests
from workflow import Workflow, ICON_USER, ICON_GROUP
API_KEY = 'your-pinboard-api-key'
class user():
def __int__(self, id, user_id, username, name, avatar_url, org_name, position_name):
self.id = id
self.user_id = user_id
self.username = username
self.name = name
self.avatar_url = avatar_url
self.org_name = org_name
self.position_name = position_name
def user(cls):
return {
'id': cls.id,
'user_id': cls.user_id,
'username': cls.username,
'name': cls.name,
'avatar_url': cls.avatar_url,
'org_name': cls.org_name,
'position_name': cls.position_name
}
class group():
def __int__(self, gid, name, avatar, owner, ownername):
self.gid = gid
self.name = name
self.avatar = avatar
self.owner = owner
self.ownername = ownername
def group(cls):
return {
'gid': cls.gid,
'name': cls.name,
'avatar': cls.avatar,
'owner': cls.owner,
'ownername': cls.ownername
}
class Search_request():
def __init__(self, search, page_id, mode, scene, folder_id):
self.search = search
self.page_id = page_id
self.mode = mode
self.scene = scene
self.folder_id = folder_id
def search_to_direct(cls):
return {
'search': cls.search,
'page_id': cls.page_id,
'mode': cls.mode,
'scene': cls.scene,
'folder_id': cls.folder_id
}
class Search_response():
def __init__(self, result):
self.__dict__ = result
''':parameter query'''
def search(query):
# 设置连接活跃状态为false,及时释放资源
session = requests.session()
session.keep_alive = False
# 构建请求行 请求头 请求体,api来自joyspace search接口
url = "https://apijoyspace.jd.com/v1/search"
temp_request = Search_request(query, 'cgHL83y1H66MU9Frjlh2', 15, 'share', '')
request_dic = search_to_direct(temp_request)
request = json.dumps(request_dic)
# cookie动态获取
cookie = browser_cookie3.chrome(domain_name='.jd.com')
headers = {
'Content-Type': 'application/json'
}
response = requests.post(url, data=request, cookies=cookie, headers=headers)
# 对结果进行反序列化,并构建支持alfred展示的json格式
result = json.loads(response.text, object_hook=Search_response)
users = result.data.users
groups = result.data.groups
# 对员工和群结果进行筛选,考虑体验问题只取前5个
u_length = len(users)
if len(users) > 5:
u_length = 5
g_length = len(groups)
if len(groups) > 5:
g_length = 5
# 构建支持alfred展示的json,包括员工和群信息
for i in range(u_length):
# users[i].avatar_url
wf.add_item(arg=users[i].username, type="user", title="姓名: " + users[i].name,
subtitle="erp: " + users[i].username, valid=True, icon=ICON_USER)
for j in range(g_length):
# group[j].avatar
wf.add_item(arg=groups[j].gid, type="group", title="群名称: " + groups[j].name,
subtitle="owner: " + groups[j].ownername, valid=True, icon=ICON_GROUP)
wf.send_feedback()
if __name__ == "__main__":
wf = Workflow()
query = sys.argv[1] # eg: query = 'jiangzixu'
search(query)
如何使用本插件
插件特性
- 支持搜索京me联系人
- 支持搜索京me群
- 支持模糊搜索并快速打开对应聊天框
使用说明
- 下载安装Alfred,需要支持powerpack,建议购买正版。
- 将远程代码clone到本地(CF搜)
- 将 『me_search.alfredworkflow』拖拽至workflow
- 修改python脚本本地路径
- 开始使用
参考文档
- Alfred 官网: www.alfredforum.com/
- electron官网: www.electronjs.org/
- 一位大佬写的electron私有协议实现相关: juejin.cn/post/688304…
- 一位大佬写的workflow实现相关: juejin.cn/post/684490…