Preface
The Mac has a memo on it, and it feels pretty handy. Then you want to do it yourself, do a similar remember gadgets to play.
Tool type: Fat service end, thin client mode. The general scenario is that the client just wants to be alerted to the issue to the server, and then with its own local scan, to meet the requirements of the memo to play frame reminder.
Recently, Redis is more fascinated by its elegant and efficient design. Although not very good for the search support, but search words using a professional search service is good. I personally prefer the purpose of the UNIX Tool Department: A tool that focuses on only one thing, which is what Redis currently embodies. Server-Side
For the server side of the design of the original intention, is a "fat", did most of the work of the form, but do it, found that the client does a lot of work in fact. The current server-side tasks are:
-Accept User Registration
-Support CRUD for memo
-"Security screening" for requests
Directory structure
➜ Server ll *.py
-rw-r--r-- 1 changba164 staff 346B Oct 14:53 datastructor.py # Common data structure Bean
- rw-r--r-- 1 changba164 staff 2.6K Oct 18:22 redishelper.py # Redis Operations-related tool classes
-rw-r--r-- 1 changba164 staff 4.6K Oct 18:42 server.py # provides service support to clients
The code is relatively simple, the following a simple look at the specific content. datastructor.py
#!/usr/bin python
# coding:utf8
# File:. py
Import sys
reload (SYS)
sys.setdefaultencoding (' UTF8 ')
import JSON
class Responsecode (object): "" ""
Service Response Code ""
"
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 Action-related tool class. "" "Def __init__ (self): self.rs = Redis. Redis (host= "localhost", port=6379, db=3, encoding= "UTF8", charset= "UTF8") # related key Self.uids = "Userids:set "Self.rank =" Unfinished:zset: "self.unfinished =" Unfinished:hash: "self.finished =" Finished:ha SH: "Def check_request_valid (self, UID, securitycode): If UID is none:return False if SE
Curitycode = = 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) Els E FAlse def add_memo (self, uid, memoid, memo= ""): If UID is none:return False memoid = Memo ID self.rs.sadd (STR (UID), memoid) Self.rs.hset (SELF.UNFINISHED+STR (UID), Memoid, Memo) Self.rs.zad
D (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.u
NFINISHED+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, mem OID): If UID is None:return None return Self.rs.hget (SELF.UNFINISHED+STR (UID), memoid) d EF Get_memos (self, UID,Reverse=true): If UID is none:return None memoids = self.get_memoids (uid, reverse) PR int 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, withs Cores=true)] Else:return [item[0] for item in Self.rs.zrange (SELF.RANK+STR (UID), 0,-1, WITHSCORES=TR
UE)]
server.py
#!/usr/bin python # coding:utf8 # file:. PY import sys reload (SYS) sys.setdefaultencoding (' UTF8 ') from flask import Fla SK, 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 = requ Est.form[' Memo '] isuserexists = Helper.check_user (uid) If isuserexists = = False:return Datastructor. Responsecode (1001, "The user has not registered yo!").
GetCode () IsValid = Helper.check_request_valid (uid, Securitycode) Logging.info ("{}: {}". Format (UID, securitycode)) if IsValid = = False:return Datastructor. Responsecode (1002, "identity information is illegal.) "). GetCode () Helper.add_memo (UID, memoid, Memo) return Datastructor. Responsecode (1000, "memo has been saved.") "). GetCode () @app. Route ("/update ", methods=[" POST ") def update (): uid = request.form[' uid '] Securitycode = Reque st.form[' Securitycode '] memoid = request.form[' memoid '] memo = request.form[' Memo '] isuserexists = Helper.che Ck_user (UID) if isuserexists = = False:return Datastructor. Responsecode (1001, "The user has not registered yo!"). GetCode () IsValid = Helper.check_request_valid (uid, securitycode) if IsValid = = False:return Datastructor . Responsecode (1002, "identity information is illegal.) "). GetCode () Helper.update_memo (UID, memoid, Memo) return Datastructor. Responsecode (1000, "mThe emo has been updated. "). GetCode () @app. Route ("/delete ", methods=[" POST ") def Deletememo (): uid = request.form[' uid '] Securitycode = r equest.form[' Securitycode '] memoid = request.form[' memoid '] isuserexists = Helper.check_user (UID) if Isuserex ists = = False:return Datastructor. Responsecode (1001, "The user has not registered yo!"). GetCode () IsValid = Helper.check_request_valid (uid, securitycode) if IsValid = = False:return Datastructor . Responsecode (1002, "identity information is illegal.) "). GetCode () Helper.delete_memo (UID, memoid) return datastructor. Responsecode (1000, "memo has been deleted/finished.") "). GetCode () @app. Route ("/detail ", methods=[" POST ") def detail (): uid = request.form[' uid '] Securitycode = Reque st.form[' Securitycode '] memoid = request.form[' memoid '] isuserexists = Helper.check_user (UID) if isuserexists = = False:return Datastructor. Responsecode (1001, "The user has not registered yo!").
GetCode () IsValid = Helper.check_request_valid (uid, securitycode) If IsValid = False: Return Datastructor. Responsecode (1002, "identity information is illegal.) "). 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 (u ID) If isuserexists = = False:return Datastructor. Responsecode (1001, "The user has not registered yo!"). GetCode () IsValid = Helper.check_request_valid (uid, securitycode) if IsValid = = False:return Datastructor . Responsecode (1002, "identity information is illegal.) "). 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, "The user has not registered yo!"). GetCode () IsValid = Helper.check_request_valid (uid, securitycode) if IsValid = = False:return Datastructor . Responsecode (1002, "identity information is illegal.) "). GetCode () memoid = Helper.get_memoids (uid, False) [0] result = {" Memoid ": Memoid," Memo ": Helpe R.get_memo (UID, memoid)} res = Datastructor. Responsecode (1000, Json.dumps ()). GetCode () return res if __name__ = ' __main__ ': app.run (host= ' localhost
', port=9999, debug=true
"Thin Client"
The client has to do is: Add memo, get the most need to deal with the memo, and the window tips and so on. At present, the task of the client is not finished, it is simple to achieve the next.
➜ 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 Impo
RT 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): "" Converts the time of the vernacular point to a timestamp, in the form: 00:00:00:00 Day: Hours: minutes: sec "" "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.utcfromtimes
Tamp (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): "" Registered user "" Def __init__ (self): pass @staticmeth OD def register (UID): If UID is none:return False url = "Http://localhost:9999/register" response = Reque Sts.post (URL, data={"UID": uid}) if Response.status_code = Response.json () [' code '] = = 1000:r
Eturn True return False class Memohelper (object): "" Client Memo Tool Class "" 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": Memo ID, "Memo": Memo} response = Requests.post (PostURL, data=payload) return Response.tex
T def getmemo (self, UID, memoid): url = Self.url.format ("detail") payload = {"UID": UID, "Securitycode": Get_security_code (UID), "memoid": memoid} response = Requests.pos
T (URL, data=payload) Return Response.text def getmemos (self, UID, reverse=true): url = Self.url.format ("lists") Payloa
D = {"UID": uid, "Securitycode": Get_security_code (UID), "reverse": Reverse} Response = Requests.post (URL, data=payload) return Response.text def getrecent (self, uid): ur L = Self.url.format ("recent") payload = {"UID": uid, "Securitycode": Get_security_code (UI d)} response = Requests.post (URL, data=payload) return Response.text def updatememo (self, UID , Memoid, Memo): url = Self.url.format ("update") payload = {"UID": uid, "security Code ": Get_security_code (UID)," memoid ": Memoid," Memo ": Memo} response = Request S.post (URL, data=payload) return Response.text def deletememo (self, UID, memoid): url = Self.url.forma T ("delete") PaylOad = {"UID": uid, "Securitycode": Get_security_code (UID), "memoid": memoid} Response = Requests.post (URL, data=payload) return Response.text class Emitter (object): "" detected
Expiration task, a reminder box pops up. "" "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): # If the time meets the requirements, emit out and find the memo farthest away from the time. 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 ()
Summary
Overall, the gadget didn't work out as I expected, with roughly the following points:
- scanning services can be said not to do.
- "Security" here is simply to limit the client request method for post, simple use of securitycode to do the next judgment (if the packet analysis, it is no use, better practice is to imitate flask use PIN code, to further improve security).
-The client frame effect is not ideal, and for a post, the corresponding GUI support has not been done, and is currently used in the command line like this:
Emitin xxxxxxx A:b:c:d
The general meaning is: Record in a day B hours C minutes after D-seconds to do xxxxxxxx matters.
Interested in the current code based on the optimization, where the right to be a draw.