Mac上有一个自带的备忘录,感受还挺好用的。而后也想本身动手,作个相似的Remember小工具来玩一下。python
工具类型:胖服务端,瘦客户端的模式。大体的场景就是客户端只管把本身想让被提醒的事项发给服务器端,而后配合本身的本地扫描,对符合要求的memo进行弹框提醒。redis
最近对Redis比较着迷一点,被其优雅高效的设计所打动。虽然对于搜索方面支持的不太好,可是搜索的话使用专业的搜索服务就行了。我我的比较崇尚Unix工具系的宗旨:一个工具只专一于作一件事,这也是Redis目前所体现的。json
对于服务器端的设计的初衷,是一个“胖胖的”,作了大部分的工做的形式,可是作着作着,发现客户端作的工做其实也蛮多的。目前服务器端的任务是:flask
目录结构安全
➜ server ll *.py
-rw-r--r-- 1 changba164 staff 346B Oct 28 14:53 datastructor.py # 常见数据结构bean
-rw-r--r-- 1 changba164 staff 2.6K Oct 28 18:22 redishelper.py # redis操做相关的工具类
-rw-r--r-- 1 changba164 staff 4.6K Oct 28 18:42 server.py # 对客户端提供服务支持复制代码
代码比较简单,下面简单来看下具体的内容。bash
datastructor.py
#!/usr/bin python
# coding: utf8
# file: .py
import sys
reload(sys)
sys.setdefaultencoding('utf8')
import json
class ResponseCode(object):
""" 服务响应码 """
def __init__(self, code, msg):
self.code = code
self.msg = msg
def getcode(self):
return json.dumps({"code":self.code, "msg":self.msg})复制代码
redishelper.py
#!/usr/bin python
# coding: utf8
# file: .py
import sys
reload(sys)
sys.setdefaultencoding('utf8')
import redis
import hashlib
import uuid
import time
class RedisHelper(object):
""" redis操做相关的工具类。 """
def __init__(self):
self.rs = redis.Redis(host="localhost", port=6379, db=3, encoding="utf8", charset="utf8")
# 相关key
self.uids = "userids:set"
self.rank = "unfinished:zset:"
self.unfinished = "unfinished:hash:"
self.finished = "finished:hash:"
def check_request_valid(self, uid, securitycode):
if uid is None:
return False
if securitycode == hashlib.md5(uid).hexdigest():
return True
return False
def register(self, uid):
if uid is None:
return False
self.rs.sadd(self.uids, uid)
return True
def check_user(self, uid):
if uid is None:
return False
return True if self.rs.sismember(self.uids, uid) else False
def add_memo(self, uid, memoid, memo=""):
if uid is None:
return False
memoid = memoid
self.rs.sadd(str(uid), memoid)
self.rs.hset(self.unfinished+str(uid), memoid, memo)
self.rs.zadd(self.rank+str(uid), memoid, int(memoid))
def update_memo(self, uid, memoid, memo):
if uid is None:
return False
if not self.rs.sismember(str(uid), memoid):
return False
self.rs.hset(self.unfinished+str(uid), memoid, memo)
return True
def delete_memo(self, uid, memoid):
if uid is None:
return False
memo = self.rs.hget(self.unfinished+str(uid), memoid)
self.rs.hset(self.finished+str(uid), memoid, memo)
self.rs.zrem(self.rank+str(uid), memoid)
return True
def get_memo(self, uid, memoid):
if uid is None:
return None
return self.rs.hget(self.unfinished+str(uid), memoid)
def get_memos(self, uid, reverse=True):
if uid is None:
return None
memoids = self.get_memoids(uid, reverse)
print memoids
memos = []
for item in memoids:
memos.append(self.rs.hget(self.unfinished+str(uid), item[0]))
return memos
def get_memoids(self, uid, reverse=True):
if uid is None:
return []
if reverse == True:
return [item[0] for item in self.rs.zrevrange(self.rank+str(uid), 0, -1, withscores=True)]
else:
return [item[0] for item in self.rs.zrange(self.rank+str(uid), 0, -1, withscores=True)]复制代码
server.py
#!/usr/bin python
# coding: utf8
# file: .py
import sys
reload(sys)
sys.setdefaultencoding('utf8')
from flask import Flask, request
import redishelper
import datastructor
import logging
import json
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s:%(levelname)s %(message)s',
datafmt="%Y-%m-%d %H:%i:%s",
filename="/Users/changba164/guo/tools/remeber/server/memo-server.log",
filemode="a"
)
app = Flask(__name__)
helper = redishelper.RedisHelper()
@app.route("/", methods=['GET', 'POST'])
def home():
return "It works!"
@app.route("/register", methods=["POST"])
def register():
uid = request.form["uid"]
helper.register(uid)
res = datastructor.ResponseCode(1000, "uid={}".format(uid))
return res.getcode()
@app.route("/add", methods=["POST"])
def add():
uid = request.form['uid']
securitycode = request.form['securitycode']
memoid = request.form['memoid']
memo = request.form['memo']
isuserexists = helper.check_user(uid)
if isuserexists == False:
return datastructor.ResponseCode(1001, "该用户还未注册哟!").getcode()
isvalid = helper.check_request_valid(uid, securitycode)
logging.info("{}: {}".format(uid, securitycode))
if isvalid == False:
return datastructor.ResponseCode(1002, "身份信息不合法!").getcode()
helper.add_memo(uid, memoid, memo)
return datastructor.ResponseCode(1000, "memo已经保存啦!").getcode()
@app.route("/update", methods=["POST"])
def update():
uid = request.form['uid']
securitycode = request.form['securitycode']
memoid = request.form['memoid']
memo = request.form['memo']
isuserexists = helper.check_user(uid)
if isuserexists == False:
return datastructor.ResponseCode(1001, "该用户还未注册哟!").getcode()
isvalid = helper.check_request_valid(uid, securitycode)
if isvalid == False:
return datastructor.ResponseCode(1002, "身份信息不合法!").getcode()
helper.update_memo(uid, memoid, memo)
return datastructor.ResponseCode(1000, "memo已经更新啦!").getcode()
@app.route("/delete", methods=["POST"])
def deletememo():
uid = request.form['uid']
securitycode = request.form['securitycode']
memoid = request.form['memoid']
isuserexists = helper.check_user(uid)
if isuserexists == False:
return datastructor.ResponseCode(1001, "该用户还未注册哟!").getcode()
isvalid = helper.check_request_valid(uid, securitycode)
if isvalid == False:
return datastructor.ResponseCode(1002, "身份信息不合法!").getcode()
helper.delete_memo(uid, memoid)
return datastructor.ResponseCode(1000, "memo已经删除/完成啦!").getcode()
@app.route("/detail", methods=["POST"])
def detail():
uid = request.form['uid']
securitycode = request.form['securitycode']
memoid = request.form['memoid']
isuserexists = helper.check_user(uid)
if isuserexists == False:
return datastructor.ResponseCode(1001, "该用户还未注册哟!").getcode()
isvalid = helper.check_request_valid(uid, securitycode)
if isvalid == False:
return datastructor.ResponseCode(1002, "身份信息不合法!").getcode()
detail = helper.get_memo(uid, memoid)
return datastructor.ResponseCode(1000, detail).getcode()
@app.route("/lists", methods=['POST'])
def lists():
uid = request.form['uid']
securitycode = request.form['securitycode']
reverse = request.form['reverse']
isuserexists = helper.check_user(uid)
if isuserexists == False:
return datastructor.ResponseCode(1001, "该用户还未注册哟!").getcode()
isvalid = helper.check_request_valid(uid, securitycode)
if isvalid == False:
return datastructor.ResponseCode(1002, "身份信息不合法!").getcode()
memos = helper.get_memos(uid, reverse)
res = datastructor.ResponseCode(1000, json.dumps((memos))).getcode()
return res
@app.route("/recent", methods=['POST'])
def recentids():
uid = request.form['uid']
securitycode = request.form['securitycode']
isuserexists = helper.check_user(uid)
if isuserexists == False:
return datastructor.ResponseCode(1001, "该用户还未注册哟!").getcode()
isvalid = helper.check_request_valid(uid, securitycode)
if isvalid == False:
return datastructor.ResponseCode(1002, "身份信息不合法!").getcode()
memoid = helper.get_memoids(uid, False)[0]
result = {
"memoid": memoid,
"memo": helper.get_memo(uid, memoid)
}
res = datastructor.ResponseCode(1000, json.dumps((result))).getcode()
return res
if __name__ == '__main__':
app.run(host='localhost', port=9999, debug=True)复制代码
客户端所要作的无非是:新增memo,得到最须要处理的memo,并进行弹窗提示等。目前客户端的任务还不算完成,也就简单实现了下。服务器
➜ client ls
testutils.py utils.py
➜ client复制代码
utils.py
#!/usr/bin python
# coding: utf8
# file: .py
import sys
reload(sys)
sys.setdefaultencoding('utf8')
import requests
import json
import hashlib
import time
import datetime
import tkMessageBox
from Tkinter import *
def get_security_code(uid):
return hashlib.md5(uid).hexdigest()
def time_to_stamp(seed):
""" 将白话点的时间转换为时间戳,格式为: 00:00:00:00 天:小时:分钟:秒 """
curtime = int(time.time())
d, h, m, s = (int(item) for item in str(seed).split(":"))
targettime = curtime + (d*86400)+ (h*3600)+(m*60)+s
return targettime
def stamp_to_time(stamp):
return datetime.datetime.utcfromtimestamp(float(stamp))
def make_dialog(timestr, msg):
tkMessageBox.showinfo(title=timestr, message=msg)
# root = Tk()
# root.title(timestr)
# frame = Frame(root)
# Label(frame, text=msg).pack()
# frame.pack(side=TOP)
# root.mainloop()
class UserService(object):
""" 注册用户 """
def __init__(self):
pass
@staticmethod
def register(uid):
if uid is None:
return False
url = "http://localhost:9999/register"
response = requests.post(url, data={"uid": uid})
if response.status_code == 200 and response.json()['code'] == 1000:
return True
return False
class MemoHelper(object):
""" 客户端memo工具类 """
def __init__(self):
self.url = "http://localhost:9999/{}"
def post(self, uid, memoid, memo):
posturl = self.url.format("add")
payload = {
"uid": uid,
"securitycode": get_security_code(uid),
"memoid": memoid,
"memo": memo
}
response = requests.post(posturl, data=payload)
return response.text
def getmemo(self, uid, memoid):
url = self.url.format("detail")
payload = {
"uid": uid,
"securitycode": get_security_code(uid),
"memoid": memoid
}
response = requests.post(url, data=payload)
return response.text
def getmemos(self, uid, reverse=True):
url = self.url.format("lists")
payload = {
"uid": uid,
"securitycode": get_security_code(uid),
"reverse": reverse
}
response = requests.post(url, data=payload)
return response.text
def getrecent(self, uid):
url = self.url.format("recent")
payload = {
"uid": uid,
"securitycode": get_security_code(uid)
}
response = requests.post(url, data=payload)
return response.text
def updatememo(self, uid, memoid, memo):
url = self.url.format("update")
payload = {
"uid": uid,
"securitycode": get_security_code(uid),
"memoid": memoid,
"memo": memo
}
response = requests.post(url, data=payload)
return response.text
def deletememo(self, uid, memoid):
url = self.url.format("delete")
payload = {
"uid": uid,
"securitycode": get_security_code(uid),
"memoid": memoid
}
response = requests.post(url, data=payload)
return response.text
class Emitter(object):
""" 检测到到期任务,则弹出一个提醒框! """
def __init__(self, uid):
self.uid = str(uid)
self.memohelper = MemoHelper()
def emit_in(self, timestr, memo):
timestamp = time_to_stamp(timestr)
self.memohelper.post(self.uid, timestamp, memo)
def emit_out(self):
# 若是时间符合要求就emit出来, 找出距离时间最远的memo。
data = self.memohelper.getrecent(self.uid)
data = json.loads(data)
data = data['msg']
data = json.loads(data)
targettime = stamp_to_time(data['memoid'])
memo = data['memo']
make_dialog(targettime, memo)
if __name__ == '__main__':
emitter = Emitter(201393260)
emitter.emit_out()复制代码
整体来讲,这个小工具没有达到个人预期效果,大体有以下几点:数据结构
emitin xxxxxxx a:b:c:d
大体的意思是: 记录 在a天b小时c分钟d秒 后要作的xxxxxxxx事项。app
有兴趣的能够在目前的代码基础上进行优化,这里权当抛砖引玉吧。ide