信息化在一个企业中的地位,要不就应当很高,要不就可有可无,不存在中间状态。
企业信息化实际上是以信息化为手段,将企业的管理思想进行落地。企业信息化的过程应当伴随这企业管理流程的梳理和优化,企业的信息化部门在一定程度上是一个管理决策部门。如果做不这一点,信息化部门就完全沦为了后台职能部门,做些简单的系统运维工作。
一个优秀的IT经理应当熟悉公司的业务流程、熟悉当前最新的技术动态、还要有能力争取到足够的资源来推动信息化建设。
信息化在一个企业中的地位,要不就应当很高,要不就可有可无,不存在中间状态。
企业信息化实际上是以信息化为手段,将企业的管理思想进行落地。企业信息化的过程应当伴随这企业管理流程的梳理和优化,企业的信息化部门在一定程度上是一个管理决策部门。如果做不这一点,信息化部门就完全沦为了后台职能部门,做些简单的系统运维工作。
一个优秀的IT经理应当熟悉公司的业务流程、熟悉当前最新的技术动态、还要有能力争取到足够的资源来推动信息化建设。
django-lb-workflow 我开发的一个Django流程引擎APP。设计之初是以使用便捷性为目标,自带了完整的模板,希望可以方便的集成到已有系统。尽管已经将django-lb-workflow做到尽量的易用,但距离真正的开箱即用还有一段距离。
Carrot Box是一个完整的Django易用,带了权限管理、部门、角色等必要模块,真正的做到开箱即用。通过对Carrot Box的定制可以方便的改造为OA、工单系统、CRM等业务系统。
Carrot Box的主要特点:
之前的django-lb-workflow范例站点已经切换到 Carrot Box。
管理员账号:admin 密码:password
切换为其他用户: http://wf.haoluobo.com/impersonate/search
退回管理员账号: http://wf.haoluobo.com/impersonate/stop
make init-pyenv
make init
make run
JetBrains的推广活动,解谜后可以获取三个月的免费订阅。由于是推广活动,所以解密过程不是非常难。真正让人头痛的是那糟糕的网速,不管挂不挂代理页面的打开都非常的慢。
48 61 76 65 20 79 6f 75 20 73 65 65 6e 20 74 68 65 20 73 6f 75 72 63 65 20 63 6f 64 65 20 6f 66 20 74 68 65 20 4a 65 74 42 72 61 69 6e 73 20 77 65 62 73 69 74 65 3f
很明显字符串的ASCII码,使用python很容易进行解码
>>> s = "48 61 76 65 20 79 6f 75 20 73 65 65 6e 20 74 68 65 20 73 6f 75 72 63 65 20 63 6f 64 65 20 6f 66 20 74 68 65 20 4a 65 74 42 72 61 69 6e 73 20 77 65 62 73 69 74 65 3f"
>>> ''.join(chr(int(e, 16)) for e in s.split(' '))
'Have you seen the source code of the JetBrains website?'
查看首页源代码找到解谜线索
JetBrains has a lot of products, but there is one that looks like a joke on our Products page, you should start there... (hint: use Chrome Incognito mode)
It’s dangerous to go alone take this key: Good luck! == Jrrg#oxfn$
根据提示,到产品页面。其中名为“JK”的产品介绍是“dare to lean more”,点击该产品继续进行挑战。
注:之前都不知道JetBrains居然已经有这多的产品了。
补完 https://jb.gg/### 后面确实的三个数字。数字为500到5000的质数个数。
到网上找了个求质数的函数,跑了一下,很快得到结果574
import math
def isprime(n):
if n < 2:
return False
for i in range(2, int(math.sqrt(n)) + 1):
if n % i == 0:
return False
return True
count = 0
for i in range(500, 5000):
if isprime(i):
count += 1
print(count)
打开上面得到的链接,其中有张图片。图片中的字符为“MPS-31816”
这个题目最坑的在于这个图片实在是太大了,约有15M,死活打不开。
https://www.jetbrains.com/MPS-31816 显示没有这个网页。MPS-31816 在JetBrains 网站找到对应页面。注:后续会知道图片上的图标是JebBrains网站的问题区的Logo。
“The key is to think back to the beginning.” – The JetBrains Quest team
Qlfh$#Li#|rx#duh#uhdglqj#wklv#|rx#pxvw#kdyh#zrunhg#rxw#krz#wr#ghfu|sw#lw1#Wklv#lv#rxu#lvvxh#wudfnhu#ghvljqhg#iru#djloh#whdpv1#Lw#lv#iuhh#iru#xs#wr#6#xvhuv#lq#Forxg#dqg#iru#43#xvhuv#lq#Vwdqgdorqh/#vr#li#|rx#zdqw#wr#jlyh#lw#d#jr#lq#|rxu#whdp#wkhq#zh#wrwdoo|#uhfrpphqg#lw1#|rx#kdyh#ilqlvkhg#wkh#iluvw#Txhvw/#qrz#lw“v#wlph#wr#uhghhp#|rxu#iluvw#sul}h1#Wkh#frgh#iru#wkh#iluvw#txhvw#lv#‟WkhGulyhWrGhyhors†1#Jr#wr#wkh#Txhvw#Sdjh#dqg#xvh#wkh#frgh#wr#fodlp#|rxu#sul}h1#kwwsv=22zzz1mhweudlqv1frp2surpr2txhvw2
很明显要用到之前的 take this key: Good luck! == Jrrg#oxfn$ 。我一开始将问题想的太复杂了,以为第一题里的内容是密钥,用xor进行解密。在网上找了个xor解密的函数,解出来一塌糊涂。
由回头仔细看了一下这所谓的密码,其实就是一个简单的字映射。
>>> s = "Qlfh$#Li#|rx#duh#uhdglqj#wklv#|rx#pxvw#kdyh#zrunhg#rxw#krz#wr#ghfu|sw#lw1#Wklv#lv#rxu#lvvxh#wudfnhu#ghvljqhg#iru#djloh#whdpv1#Lw#lv#iuhh#iru#xs#wr#6#xvhuv#lq#Forxg#dq
g#iru#43#xvhuv#lq#Vwdqgdorqh/#vr#li#|rx#zdqw#wr#jlyh#lw#d#jr#lq#|rxu#whdp#wkhq#zh#wrwdoo|#uhfrpphqg#lw1#|rx#kdyh#ilqlvkhg#wkh#iluvw#Txhvw/#qrz#lw“v#wlph#wr#uhghhp#|rxu#iluvw#s
ul}h1#Wkh#frgh#iru#wkh#iluvw#txhvw#lv#‟WkhGulyhWrGhyhors†1#Jr#wr#wkh#Txhvw#Sdjh#dqg#xvh#wkh#frgh#wr#fodlp#|rxu#sul}h1#kwwsv=22zzz1mhweudlqv1frp2surpr2txhvw2"
>>>
>>> c = ord('J') - ord('G')
>>> ''.join(chr(ord(e) - c) for e in s)
'Nice! If you are reading this you must have worked out how to decrypt it. This is our issue tracker designed for agile teams. It is free for up to 3 users in Cloud and for 10
users in Standalone, so if you want to give it a go in your team then we totally recommend it. you have finished the first Quest, now it’s time to redeem your first prize. Th
e code for the first quest is “TheDriveToDevelop”. Go to the Quest Page and use the code to claim your prize. https://www.jetbrains.com/promo/quest/'
项目地址(Go): https://github.com/vicalloy/telegram-shell-bot-go
由于对Go不熟悉,因此之前版本的 Telegram Shell Bot 采用Python实现。在Python版发布后就开始尝试使用Go重新实现,毕竟之所以要做这东西也是想借个小程序体验一下Go语言。
随着微服务的兴起,相较以往服务的粒度可以拆分的更细。系统复杂度更多的转变为微服务构架设计的复杂度。服务拆分后每个具体的服务的复杂度将降低,系统对程序语言本身的构架能力的依赖会减少很多。同时在服务拆分后,各个服务组件可以灵活的采用适合的技术来完成工作。
Go语言本身极度精简(简陋),如果要象Java一样搭建一个单体的巨型项目会存在一定困难。Go的高性能,异步,加之足够简单,使Go在一些对性能要求较高,但业务复杂度相对较低的场合会非常适合。
Go可能永远不能变的同Java一样流行,但Go已经足够成功,值得去体验。
Telegram Shell Bot Go 是我第一次使用Go写东西,由于只是一个小项目体验还不算特别深。Go语言中最精华的并发相关内容(goroutine / channel / select)并没有用到。
总的来说Go有着还不错的开发体验,但另一方便由于习惯了Python,Go又有不少让我用的不是特别舒服的地方。有人说Go是better C,我个人还是比较认可这个观点,相比其他语言Go很像C语言。
项目地址: https://github.com/vicalloy/telegram-shell-bot
很早之前就打算做这么一个东西,后来因为要调用的脚本是 Python 写的,于是直接在 Bot 里调用 Python 代码。 近期把这个想法重新实现了。
网上也有类似的项目,其中一些比较简单,甚至都没有对用户做校验,这样只要有人可以连上你的机器人就可以控制你的机器。类似的机器人里功能最强的是shell-bot。”shell-bot”模拟了一个 tty,实现较复杂,没有仔细研究。
Telegram Shell Bot目前提供的功能有:
; 跳过命令检查,类似的字符也应当加到字符串黑名单中。/tasks命令查看有哪些命令还在执行中,并可以通过 /kill pid 的方式强制结束命令。echo password | su -S 的方式实现,需要自行评估风险。前几天又看了一下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 模块。对于只有一个事项名称和内容的流程,可以不写任何代码,只需要在系统中配置流程节点。做了上面一些更新后,对这个项目又开始有些倦怠了。下面的这些问题可能要等到下次再对这个项目提起兴趣的时候了。
Class-based views 中,可以通过Minxin灵活配置。注:Django REST framework权限部分的设计比较完善,相关代码可以直接移植过来。最近重新开始玩Ingress。好多年没玩,主要玩家已由QQ转战Telegram了。还有玩家专门为Telegram做了个Bot用来做新人接待、面基统计等相关工作。稍微研究了一下Telegram的Bot实现,发现Telegram API功能非常强大,而且使用起来也很简单,可以轻易的做出自己的机器人。
如果你想更多的了解Telegram Bot可以做什么,怎么创建一个自己的Bot建议阅读Telegram的官方文档 Bots: An introduction for developers。如果你和我一样使用Python进行开发,可以使用python-telegram-bot进行开发。
一般情况下Bot都是在接收到用户的命令后被动的回复信息,如果希望机器人主动推送消息可以先手动查询chat id,然后Bot发送消息时指定为该chat id。获取chat id的方法如下:
@bot /xxx给机器人发消息。https://api.telegram.org/bot<YourBOTToken>/getUpdates获取消息。getUpdates接口后将得到一组JSON数据,里面哪个是chat id还是比较容易识别出来的。发送命令51job,这个机器人会调用jobmonitor检查51job的岗位更新情况。
import logging
from telegram.ext import Updater, CommandHandler
from telegram.ext.dispatcher import run_async
from job import qcwy as job_qcwy
TOKEN = 'XXX'
# Enable logging
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
level=logging.INFO)
logger = logging.getLogger(__name__)
@run_async
def start(bot, update):
"""Send a message when the command /help is issued."""
bot.send_message(
chat_id=update.message.chat_id,
text="Hi! I'm vicalloy's Bot. \r\n"
"/51job update 51job. n"
)
@run_async
def qcwy(bot, update):
# 为防止其他人恶意向机器人发送信息触发该命令,这里还需要对发送人做个判断,只响应特定用户的请求。
job_qcwy()
def error(bot, update):
"""Log Errors caused by Updates."""
logger.warning('Update "%s" caused error "%s"', bot, update.error)
def main():
updater = Updater(TOKEN)
dp = updater.dispatcher
dp.add_handler(CommandHandler("start", start))
dp.add_handler(CommandHandler("help", start))
dp.add_handler(CommandHandler("51job", qcwy))
dp.add_error_handler(error)
updater.start_polling()
updater.idle()
if __name__ == '__main__':
main()
项目地址: https://github.com/vicalloy/jobmonitor/
一个监控招聘网站工作岗位更新情况并发送通知的小工具。很早之前写的一个小脚本,近期重构了一下,让这个脚本可以更方便的扩展。
目前只做了前程无忧以及V2EX的支持,欢迎添加其他网站的支持。
$ mkdir jobs
$ cd jobs
$ pip install pipenv --upgrade
$ pipenv --python 3.6
$ pipenv shell
$ pipenv install lbjobmonitor
# 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()
注: 还为这个工具做了一个 web 前端界面 https://github.com/vicalloy/jobmonitorweb/ 可通过 web 端查看推送信息。不过个人觉得用 slack 或 telegram 接收和查看推送信息更方便。这个项目里使用了Django Channels来做Web端的实时消息推送,如果感兴趣可以参考一下。
最初也考虑过将这个功能做成服务,用户可以通过WEB界面配置自己的订阅规则和消息的接收方式。不过一般网站都会有反爬虫的处理,如果服务器对一个网站访问过于频繁很可能会被该网站给ban掉,这个方案不可行。
当然,如果真想把这个功能做成服务还是有办法的。可以将主要功能用JS实现,用户将数据抓取的规则配置和历史记录保存在服务器。用户打开浏览器手动刷新岗位信息,数据抓取通过用户的浏览器完成。
2018年接手了一些不是自己很擅长的工作,工作完成的也不是很让自己满意。
希望2019能有趣一些。