分类目录归档:vicalloy的庄家

Go语言版 [Telegram Shell Bot]及Go的初体验

项目地址(Go): https://github.com/vicalloy/telegram-shell-bot-go

由于对Go不熟悉,因此之前版本的 Telegram Shell Bot 采用Python实现。在Python版发布后就开始尝试使用Go重新实现,毕竟之所以要做这东西也是想借个小程序体验一下Go语言。

我对Go语言的一些看法

随着微服务的兴起,相较以往服务的粒度可以拆分的更细。系统复杂度更多的转变为微服务构架设计的复杂度。服务拆分后每个具体的服务的复杂度将降低,系统对程序语言本身的构架能力的依赖会减少很多。同时在服务拆分后,各个服务组件可以灵活的采用适合的技术来完成工作。

Go语言本身极度精简(简陋),如果要象Java一样搭建一个单体的巨型项目会存在一定困难。Go的高性能,异步,加之足够简单,使Go在一些对性能要求较高,但业务复杂度相对较低的场合会非常适合。

Go可能永远不能变的同Java一样流行,但Go已经足够成功,值得去体验。

Go开发的相关资源

  • Tour of Go 官方的简明教程,可以快速浏览一遍了解Go的主要语言特性。代码编写过程中也可以作为参考手册。
  • Go标准类库 Go的标准类库。
  • Vim Go Vim的Go语言插件,支持语法检查、自动格式化、自动补全等特性。注:挺想试试GoLand,不过GoLand只有30天的试用期。
  • 在国内Go的官网访问不是特别方便,可以使用国内翻译的中文教程。Go标准类库(中文版) Tour of Go(中文版)

开发过程中的实际体验

Telegram Shell Bot Go 是我第一次使用Go写东西,由于只是一个小项目体验还不算特别深。Go语言中最精华的并发相关内容(goroutine / channel / select)并没有用到。

总的来说Go有着还不错的开发体验,但另一方便由于习惯了Python,Go又有不少让我用的不是特别舒服的地方。有人说Go是better C,我个人还是比较认可这个观点,相比其他语言Go很像C语言。

优点

  • Python使用缩进语法保证代码的整洁。Go则直接内置代码格式化工具来强制保证代码格式的一致性。
  • 之前听说Go的包管理很差劲。这次使用已经有go mod的支持,用下来体验还不错。
  • GC、性能好、编译速度快等。

不太习惯的地方(不一定是缺点)

  • 基础类型同Python相比差太多。Slice和Python里的List相对应,但功能方面差非常多。其中一个简单的删除对象的功能都需要自己实现。不清楚这是否是出于性能的考虑,需要让用户明确清楚相关操作的时间复杂度。但使用起来真的非常不方便。用了其他开发语言后,更让人怀念Python的列表推导。
  • Go在语法层面比较简单,相对较新的概念也就异步相关的内容(这部分Go设计的不错,实际上也并不难理解),真正难的还是适应Go的编程风格。Go的Telegram类库API风格同Python版有较大差别。我想API的风格差异更多的还是同语言本身风格差异相关的。要完全适应Go的编程风格可能需要先找几个代码写的比较好的项目先学习一下。

[Telegram Shell Bot]远程执行 Shell 命令的 Telegram 机器人

项目地址: https://github.com/vicalloy/telegram-shell-bot

很早之前就打算做这么一个东西,后来因为要调用的脚本是 Python 写的,于是直接在 Bot 里调用 Python 代码。 近期把这个想法重新实现了。

网上也有类似的项目,其中一些比较简单,甚至都没有对用户做校验,这样只要有人可以连上你的机器人就可以控制你的机器。类似的机器人里功能最强的是shell-bot。”shell-bot”模拟了一个 tty,实现较复杂,没有仔细研究。

Telegram Shell Bot目前提供的功能有:

  1. 鉴权,只有在许可列表里的用户才能对机器人发号指令。
  2. 支持命令的黑白名单。注:为避免使用 ; 跳过命令检查,类似的字符也应当加到字符串黑名单中。
  3. Shell 命令的执行,如 ls、cat、ps 等。
  4. 长时间执行命令的管理。如执行 wget 操作,只返回最开始几条输出(防止一直刷屏)。之后可以通过/tasks命令查看有哪些命令还在执行中,并可以通过 /kill pid 的方式强制结束命令。
  5. 支持 sudo。注:sudo 通过 echo password | su -S 的方式实现,需要自行评估风险。
  6. 自定义脚本放在 ./scripts 目录,通过 /script 命令可以快速访问这些脚本并执行。

django-lb-workflow 近期更新

前几天又看了一下Django的Class-based views,想着django-lb-workflow的一些设计似乎还需要优化一下,于是又去折腾了一下django-lb-workflow。

Class-based views提高了代码的复用性,但过多的Mixin和继承层次让代码变的不那么容易理解。而且在面对一些“特殊”需求时会变的有些别扭。

一个列表界面搭配一个查询表单是一个很常见的操作,但想要在Django默认的ListView里添加这个查询Form并不太容易。在ListView里通过重载get_queryset方法修改查询内容。通过重载get_context_data修改context内容。按照我的理解合理的方式应当是在get_queryset函数中创建form,在form校验成功后使用form的参数作为查询条件返回查询后的queryset。但get_queryset无法直接同get_context_data函数打交道,必须先将 self.form = form 在到get_context_data中通过self.form来获取form信息。这个过程变的非常不直观和奇怪。最终我还是选择不直接继承ListView,在自定义的ListView中重载get函数,在get函数中处理form和查询。

主要更新

  • 增加“添加会签人”的功能。只有在被加签的人处理完成后,流程才可以流转到下一节点。
  • 去掉 django-el-pagination,使用Django自带的分页功能。
  • 为简化系统使用,增加 simplewf 模块。对于只有一个事项名称和内容的流程,可以不写任何代码,只需要在系统中配置流程节点。

待解决的一些问题

做了上面一些更新后,对这个项目又开始有些倦怠了。下面的这些问题可能要等到下次再对这个项目提起兴趣的时候了。

  • 流程的查看、编辑等权限通过在settings里配置校验函数实现。事实上并不太直观,操作性上也不是特别好。更合理的方式还是将权限控制这部分也放到 Class-based views 中,可以通过Minxin灵活配置。注:Django REST framework权限部分的设计比较完善,相关代码可以直接移植过来。
  • 目前还不支持Django 3.0。Django 3.0移除了部分兼容性代码,导致系统跑不起来。
  • 文档…

换回自己的VIM配置文件

用过一段时间网上的通用VIM配置文件。使用通用配置文件本来是为了省心,实际用下来却并不省心。通用配置加载的东西是在太多,出了问题很难排查。默认配置里有部分不符合自己习惯的东西也很难改,修改之后更是衍生出一堆奇怪的问题。

最近新装了一台主机,趁着设置电脑的时候将VIM的配置重新整理了一遍,改用自己的VIM配置文件。

当前VIM下的插件管理工具已经很完善,插件的添加和更新都很方便。将自己常用的插件整理了一下,并使用vim-plug对插件进行管理。在加上少量自定义设置后,VIM的配置文件就好了。在换回自己的VIM配置后,VIM终于又重新开始变的好用了。

我的VIM设置可以在 这里 找到。

招聘网站岗位信息更新监控工具

项目地址: https://github.com/vicalloy/jobmonitor/

image codecov.io

一个监控招聘网站工作岗位更新情况并发送通知的小工具。很早之前写的一个小脚本,近期重构了一下,让这个脚本可以更方便的扩展。

目前只做了前程无忧以及V2EX的支持,欢迎添加其他网站的支持。

目的

  • 招聘网站的问题
    • 招聘网站每天都会显示大量的岗位更新,但大多岗位都是常年发布,要从这些岗位里过滤出真正更新的岗位并不容易。
    • 招聘网站的搜索功能还不够完善,做不了高度个性化的定制化搜索条件。
    • 专业论坛的招聘版块,几乎没有搜索功能。
  • 这个工具可以做什么
    • 支持定制招聘网站搜索条件,并对网站提供的标准搜索功能进行少量增强。
    • 对检索到的工作岗位进行过滤,如果该岗位之前已发布过,自动忽略。
    • 可部署在服务器上,设置定时任务方式定时推送岗位更新,支持多种消息推送方式。
    • 新工作岗位通知方式支持:显示到控制台、保存到文件、发送到 Slack (强烈推荐 Slack )。注:如果想支持微信、邮件的通知,需要自行扩展。
    • 内置了 51JOB 和 V2EX 的支持。注:如需要支持其他招聘网站,需要自行进行扩展。

使用范例

  • 初始化项目
$ mkdir jobs
$ cd jobs
$ pip install pipenv --upgrade
$ pipenv --python 3.6
$ pipenv shell
$ pipenv install lbjobmonitor
  • 创建jobs.py。使用python jobs.py执行查询。
  • 可在服务器上使用 crontab 设置定时任务,定期检查
# jobs.py
import os
from lbjobmonitor.message import CLIMessageBackend
from lbjobmonitor.message import FileMessageBackend
from lbjobmonitor.monitor import QCWYJobMonitor
from lbjobmonitor.storage import JobMonitorJsonStorage
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
DATA_DIR = BASE_DIR
def qcwy():
    params = {  # 51job 的查询参数。51job 设置好查询条件后发起查询,通过 chrome 的调试功能查看请求的具体参数。
        'saltype': '',  # 薪资范围
        'keyword': 'python',  # 关键词
        'postchannel': '0000',
        'keywordtype': '2',
        'jobarea': '080200',  # 地区编码
        'pagesize': '5',  # 每页记录数
        '': ''
    }
    storage = JobMonitorJsonStorage(base_path=DATA_DIR)  # 使用 JSON 方式将工作列表保存到当前目录
    message_backend_list = [  # 显示的推送方式
        CLIMessageBackend(),  # 显示到控制台
        FileMessageBackend(fn=os.path.join(DATA_DIR, 'jobs.txt'))  # 保存到文件
    ]
    monitor = QCWYJobMonitor(
        storage=storage, message_backend_list=message_backend_list)
		# monitor.max_page_idx = 1  # 最多查询页数,设置成 1 方便调试
    skip_words = ['AI']
    monitor.monitor_jobs(params=params, skip_words=skip_words)  # 执行查询
if __name__ == "__main__":
    qcwy()

代码导航

  • monitor.py
    • JobMonitor 工作岗位监控基础类
    • QCWYJobMonitor 51JOB岗位监控实现
    • V2exJobMonitor V2EX岗位监控实现
  • storage.py
    • JobMonitorStorage 存储区基础类
    • JobMonitorJsonStorage 将信息以json方式保存到文件的存储区实现
  • message.py
    • BaseMessageBackend 消息发送处理后端基础类
    • IMMessageBackend IM类消息的后端基础类
    • CLIMessageBackend 将消息发送到控制台
    • FileMessageBackend 将消息保存到文件
    • SlackMessageBackend 将消息发送到Slack
    • TelegramMessageBackend 将消息发送到Telegram
  • models.py
    • Job 岗位信息基础数据类
    • QCWYJob 51JOB的岗位信息解析类
    • V2exJob V2EX的岗位信息解析类

注: 还为这个工具做了一个 web 前端界面 https://github.com/vicalloy/jobmonitorweb/ 可通过 web 端查看推送信息。不过个人觉得用 slack 或 telegram 接收和查看推送信息更方便。这个项目里使用了Django Channels来做Web端的实时消息推送,如果感兴趣可以参考一下。

中心化服务问题

最初也考虑过将这个功能做成服务,用户可以通过WEB界面配置自己的订阅规则和消息的接收方式。不过一般网站都会有反爬虫的处理,如果服务器对一个网站访问过于频繁很可能会被该网站给ban掉,这个方案不可行。

当然,如果真想把这个功能做成服务还是有办法的。可以将主要功能用JS实现,用户将数据抓取的规则配置和历史记录保存在服务器。用户打开浏览器手动刷新岗位信息,数据抓取通过用户的浏览器完成。

为django-lb-workflow增加Pipenv

不知道是否是有项目在用(或是计划使用)django-lb-workflow,最近陆陆续续的收到一些issue。其中大多是咨询django-lb-workflow如何使用,也有些windows平台下的bug,还有就是因为python第三方库版本问题导致跑不起来的。
我使用virtualenv来创建虚拟环境,并使用pip(requirements.txt)管理第三方依赖。在指定依赖时通常都只会指定所需的最低版本,过一段时间不维护依赖就要出问题。
近年来Pipenv开始流行,目前看来很有希望成为今后python项目的标配。
Pipenv为您的项目创建和管理Python虚拟环境,并通过Pipfile 和 Pipfile.lock这 两个文件来管理项目中的Python依赖包。对我来说Pipenv的Pipfile.lock提供了对所有依赖层级的Python包的版本锁,可以有效的避免由于requirements.txt过于简单导致的第三方库版本问题。
希望用了Pipenv后,因为第三方库版本问题导致程序跑不起来的问题可以不再出现。

从HHVM换回到PHP-FPM

之前一直用PHP-FPM作为PHP的解析器,上次在将博客迁移到linode的时候换成了HHVM。换到HHVM后博客就一直不太稳定,经常莫名其妙的down掉。
前两天博客有down掉了,重启HHVM也不解决问题,干脆换回了PHP-FPM。希望之后博客能稳定一些。

关闭“似水流年”

将服务器迁移到linode后, jstwind.com 就一直有些问题。因为没有什么人访问也懒得去改了。后来想想,既然没什么人用,也懒得维护,还是把网站关了。

“似水流年”是我做的一个用于编辑时间线的网站,用户可以在上面创建和分享时间线。网站前端用的是Bootstrap,当时Bootstrap刚出来没多久,我也是第一次使用Bootstrap,因此前端部分写的非常烂。为了保证良好的用户体验,时间线的编辑部分采用了AJAX,当时很多时间都花在了这上面。

网站关了,域名还会继续留着,说不定哪天用来做个新“玩具”。

代码托管在Github上,你可以在这里找到: https://github.com/vicalloy/timeline-site

开始写lbworkflow的文档

文档是一个开源项目很重要的一个组成部分,在我看来一个没有文档的开源项目不是一个合格的项目。最近开始给 django-lb-workflow 写文档。

对我来说喜欢写代码多过写文档,特别是在我英文不灵光的情况下。工作流本身就是一个挺复杂的东西,也不知道最终写出来的文档别人能不能看懂。

目前文档只完成了很小的一部分。里面有一个简单的例子,照葫芦画瓢应当也基本能知道怎么使用了。
文档地址: http://django-lb-workflow.rtfd.io/

lbworkflow预览版

django-lb-workflow 是我开发的一个工作流组件。目前还有很多工作要做,不过主体功能已基本可以使用了。在我看来还远没有到可以发布的阶段,不过还是很想先宣传一下,也希望能收到一些反馈。

关于为啥要挖这个坑,以及一下想法可以见之前的博客: 挖了一个新坑-Django的工作流引擎

演示项目地址:
http://wf.haoluobo.com/
管理员用户:
用户名:admin 密码:password
登陆后快速切换用户:
http://wf.haoluobo.com/impersonate/search/
http://wf.haoluobo.com/impersonate/stop/
流程配置信息查看:
http://wf.haoluobo.com/admin/lbworkflow/

目前还处于零文档的情况,用法只能先看代码了。
测试用例里是一个请假的演示:
https://github.com/vicalloy/django-lb-workflow/tree/master/lbworkflow/tests/leave