SwitchHosts! 支持 Alfred 小记

很早就有人建议让 SwitchHosts 支持 Alfred ,我也曾多次想过开发这个功能,但拖延症很严重,一直没有动手😅。最近注意到 SwitchHosts 在 GitHub 上已经有超过 2000 个 star,开心的同时也觉得压力开始大了起来,于是抽空认真梳理了一遍代码,做了若干改造,修复了若干遗留问题(当然,还有一些仍待处理),最后,添加了对 Alfred workflow 的支持。

SwitchHosts-with-alfred

当然,由于 Alfred 仅支持 macOS,这个功能也只支持 macOS。

使用方法:

  1. 下载 SwitchHosts 最新版本(v3.3.0 或更新版本)
  2. 下载对应的 workflow 文件并安装
  3. 在 Alfred 界面输入关键词 swh,即可列出当前 hosts 方案列表,并可直接在下拉菜单中进行切换

效果如下:

下面记录一下工作原理以及开发说明。

工作原理

工作原理非常简单:SwitchHosts 启动时,开启一个 HTTP 服务,提供了 list 以及 toggle 两个接口,顾名思义,list 就是列出所有可用的 hosts 方案,toggle 则是切换指定方案。接下来,Alfred 则根据用户指令,请求对应的接口。如下图所示:

HTTP 服务使用了 express.js 来实现(源码),随 app 启动,监听 50761 端口。启动 app 后,你可以在浏览器中访问 http://127.0.0.1:50761 ,如果能正常打开页面,并看到“Hello SwitchHosts”的字样,表示 HTTP 服务已正常启动。

list 接口(源码)的访问地址为 http://127.0.0.1:50761/api/list ,返回一个 JSON ,格式形如:

{
  "success": true,
  "data": [
    {
      "id": "1490959856569-442720",
      "title": "default",
      "content": "# ...",
      "on": true,
      "where": "local",
      "url": "",
      "last_refresh": null,
      "refresh_interval": 0,
      "include": []
    },
    {
      "id": "1490959856569-329205",
      "title": "my Tests",
      "content": "# ..",
      "on": true,
      "where": "local",
      "url": "",
      "last_refresh": null,
      "refresh_interval": 0,
      "include": []
    },
    ...

注意其中每个 hosts 方案都有一个 id,这个 id 将会在下面的 toggle 接口中使用。

toggle 接口(源码)的访问地址为 http://127.0.0.1:50761/api/toggle?id={id} ,它接受一个 id 参数,查询对应的 hosts,并进行切换。

目前 SwitchHosts 只提供了 Alfred 支持,不过有了 listtoggle 这两个接口,理论上用户可以为任何第三方工具开发 SwitchHosts 的支持。

代码实现

接下来就是 Alfred 的部分了,源码在这里,使用的是 Python 作为开发语言,参考了这个教程

其中生成列表的代码如下:

# -*- coding: utf-8 -*-

import sys
# the workflow package below is download from:
# https://github.com/deanishe/alfred-workflow/releases
from workflow import Workflow, ICON_WEB, web

def get_subtitle(item):
    content = item.get('content', '')
    return content.partition('\n')[0].strip()

def main(wf):
    url = 'http://127.0.0.1:50761/api/list'
    r = web.get(url)

    # throw an error if request failed
    # Workflow will catch this and show it to the user
    r.raise_for_status()

    # Parse the JSON returned by pinboard and extract the posts
    result = r.json()
    items = result['data']

    # Loop through the returned posts and add an item for each to
    # the list of results for Alfred
    for item in items:
        on = item.get('on', False)
        wf.add_item(title=item['title'],
                    subtitle=get_subtitle(item),
                    arg=item['id'],
                    valid=True,
                    icon='on.png' if on else 'off.png')

    # Send the results to Alfred as XML
    wf.send_feedback()

if __name__ == '__main__':
    my_wf = Workflow()
    sys.exit(my_wf.run(main))

用到的 python workflow 模块可以从这儿下载。

用户选中切换的脚本则非常简单,传入 id 后,访问对应的 toggle 接口即可,Alfred 中的 workflow 脚本只有一行:

curl 'http://127.0.0.1:50761/api/toggle?id={query}'

下载

最后,再贴一下 Alfred workflow 的下载地址,使用过程中有任何问题,欢迎给我提 issue

后续

【2022-06-08 更新】

macOS 12.3 中移除了 Python 2,导致原来的 Alfred workflow 失效(参见 #692),于是用 JavaScript 重写了这个 workflow,版本号升级为 1.3,下载地址不变。

分类:编程标签:SwitchHostsAlfredElectron

相关文章:

评论:

dorcat

在WIN10中以管理员身份打开,依然弹出错误,没有权限,提示用管理员身份打开软件。

oldj

可能是电脑上的安全软件引起的,比如360安全卫士、卡巴斯基等。试试将 SwitchHosts! 添加到安全软件的受信任组,并在文件监听里设置 hosts 为排除项。参见 #158

ZY

我的也出现这个问题, 未安装安全软件,win10防火墙已添加信任软件

Shenlei Zhu

有了这个,是不是就不用启动软件来切换hosts啦?

oldj

Switchhosts! 还是要运行,不过切换时不用通过它,它一直在后台运行就行。

lhc

有点尴尬的地方是,如果我想关闭一个开启一个,这个好像没有办法那样操作,还是要到界面上进行设置

oldj

嗯,要操作两次,或者在选项中设置为单选模式。

在 Windows 上如何管理 Hosts?这里有 3 款小工具推荐给你 | 系统天空

[…] 的 macOS 版本里,还支持 Alfred 快速调用。你可以在作者网站主页了解更多软件支持 Alfred 背后的开发故事。在一键切换、Hosts […]

在 Windows 上如何管理 Hosts?这里有 3 款小工具推荐给你 | ZhangXiaoBi

[…] 的 macOS 版本里,还支持 Alfred 快速调用。你可以在作者网站主页了解更多软件支持 Alfred 背后的开发故事。在一键切换、Hosts […]

发表评论: