饭否定时提醒工具

深柳堂|饭否应用:定时提醒工具

是什么

使用GAE写了一款饭否提醒工具,@timers其作用是在规定的时间给饭否以提醒。当然,内容可以自定义,比如几点几分去偷人家的菜,等等,方便一直泡在饭否上的饭友使用全新的方式来提醒自己。当然了,如果饭否支持将@消息和私信发到手机上的话,这款应用会更有用。

怎么用

  1. @timers为好友。

  2. @timers发送格式如"@timers dp 10 任意提醒"消息。消息可以分4段:回复段,模式段,时间段,内容段。段之间以1个或多个半角空格隔开。

  3. 回复段:@timers 固定。之所以要加@timers为好友,是为了让@timers能收到您的消息。(如果您没有加@timers为好友,其实也可以点击@timers的任意一条消息点“回复”,@timers也能收到你的消息的。

  4. 模式段:即提醒方式,d为直接回复(direct reply)给您;p为私信回复(private)给您;可用模式为d或p或dp。
    2009.6.19更新:新增消息确认功能,@timers 收到消息后会及时回复一条“收到,我将于xxxx-xx-xx xx:xx提醒您。谢谢使用!”此功能默认开启。如果不需要此功能,只需要在模式段加入q即可。q为quiet之意。现在可用的模式有:dpq,其中dp选一或二,q可选可不选。
  5. 时间段:即何时提醒您。它支持如下方式的时间格式:
    • 正整数时间格式: @timers dp 20 告诉我做某事。#此处的20可以是任意的正整数。
    • 指定当天的几点几分:@timers dp 23:40 告诉我做某事。#程序会在当天的23:40向您发送提醒。(如果发送消息的当前时间是18:00,而发给@timers的提醒时间为11:00,则它收到消息后,1分钟内会提醒您。因为时间已经过了。这是一个特例。)
    • 指定当月某日的几点几分:@timers dp 20 23:40 告诉我做某事。#程序会在当月20日的23:40向您发送提醒。
    • 指定某月某日的几点几分:@timers dp 12-20 23:40 告诉我做某事。#程序会在12月20日的23:40向您发送提醒。
    • 指定具体的某年某月某日的几点几分:@timers dp 2010-12-20 23:40 告诉我做某事。#程序会在2010年12月20日的23:40向您发送提醒。
    • 需要说明的是,dp、数字、空格、中划线、冒号,全部都是半角字符。否则程序无法识别时间、提醒格式。
  6. 消息段。这段即是提醒正文部分。没有特殊要求,只要不超过饭否规定的字数即可。

    怎样,不算太复杂吧?

为什么

这里说一下该程序的实现思路。与上一篇《GAE牛刀小试:从twitter到9911同步消息》类似,此程序同样使用GAE,使用cron。

  • 程序每分钟执行一次。
  • 每次执行,先查询尚未提醒的任务。
  • 对于每一条未执行的任务,如果提醒时间小于或等于当前时间,则执行提醒(@或私信),同时将消息的状态设置为已经执行;如果大于,则略过。
  • 查询数据库中最新消息的ID。
  • 以此ID为参数,通过API读取@timers新收到的所有消息,保存在数据库中。

帮助我

如果您有任何建议、意见,请告诉我,我会修改程序,争取让它更好用。

源代码

公布源代码是个好习惯。比起自己的硬盘来,我相信网络空间更持久。虽然they say nothing lasts forever。 点击下面右侧的向下的▲查看源码。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#latest edit: 2009.06.19 

#to ensure the utf8 encoding environment
import sys
default_encoding = 'utf-8'
if sys.getdefaultencoding() != default_encoding:
    reload(sys)
    sys.setdefaultencoding(default_encoding)

import urllib
import base64
import re
import time                                 #time zone convertion

from google.appengine.api import urlfetch
from google.appengine.ext import db

def time_from_0_to_8(timestr,timezone=8): 

    TIMEFORMAT="%a %b %d %X +0000 %Y"
    #Sat Jan 03 23:08:54 +0000 2009
    ISOTIMEFORMAT='%Y-%m-%d %X'
    x=time.strptime(timestr, TIMEFORMAT)
    m=time.mktime(x)+60*60*timezone
    p=time.strftime(ISOTIMEFORMAT,time.localtime(m))
    return p

def timestr_add_mins(timestr,mins=0,future=""):
    '''
    receive time str, format like: 2009-06-10 13:00:33
    and integer mins
    return seconds;
    '''
    ISOTIMEFORMAT='%Y-%m-%d %X'
    x=time.strptime(timestr, ISOTIMEFORMAT)
    m=time.mktime(x)+60*mins
    p=time.strftime(ISOTIMEFORMAT,time.localtime(m))
    return p

def add_time(p_time="",send_time=""):
    ISOTIMEFORMAT='%Y-%m-%d %X'

    now=time.localtime()
    #print now.tm_year
    p=""
    match = re.search(
	    r"""(?:(?P\d{4})-(?=\d+))?
	(?:(?:(?P\d{1,2})-)?(?P\d{1,2})\s+)?
	(?P\d{1,2}):(?P\d{1,2}) |
	(?P\d+)
	    """, p_time, re.VERBOSE)
    if match:
        min3 = match.group("min3")
        if min3:
            x=time.strptime(send_time, ISOTIMEFORMAT)
            x=time.mktime(x)+int(min3)*60
            x=time.strftime(ISOTIMEFORMAT,time.localtime(x))
            return x
        year = match.group("year")
        if year==None:
            year=now.tm_year
        month = match.group("month")
        date = match.group("date")
        if month==None :
            month=now.tm_mon
        if date==None:
            date=now.tm_mday
        hour=match.group("hour")
        mins=match.group("mins")
        return """%s-%02d-%02d %02d:%02d:00"""%(year,int(month),int(date),int(hour),int(mins))

class Msgs(db.Model):
    msg_id = db.StringProperty()
    time = time = db.StringProperty() #the excution time; format: 2009-01-31 23:59
    send_time = db.StringProperty()
    d = db.BooleanProperty(default=False)
    p = db.BooleanProperty(default=False)
    q = db.BooleanProperty(default=False)
    task= db.TextProperty()
    user_id = db.StringProperty()
    user_name = db.StringProperty()
    done = db.BooleanProperty(default=False)
    def print_all(self):
        print "ID:%s in %s mins was %s, DPD:%d%d%d, by %s(%s). Task:%s" % \
        (self.msg_id,self.time,self.send_time,self.d,self.p,\
        self.done,self.user_name,self.user_id,self.task)

def reply_msg(user,sn,msg,reply_id=""):

    auth=base64.b64encode(user+":"+sn)
    auth='Basic '+auth
    form_fields = {
        "status": msg,
        "in_reply_to_status_id":reply_id
    }
    form_data = urllib.urlencode(form_fields)

    result = urlfetch.fetch(url="""http://api.fanfou.com/statuses/update.xml""",\
            payload=form_data,
            headers={'Authorization':auth},
            method=urlfetch.POST
            )

    if result.status_code != 200:
        print "Send Msg:%s Error!"%msg

def private_msg(user,sn,msg,to_id):
    auth=base64.b64encode(user+":"+sn)
    auth='Basic '+auth
    form_fields = {
        "text": msg,
        "user":to_id
    }
    form_data = urllib.urlencode(form_fields)

    result = urlfetch.fetch(url="""http://api.fanfou.com/direct_messages/new.xml""",\
            payload=form_data,
            headers={'Authorization':auth},
            method=urlfetch.POST
            )

    if result.status_code != 200:
        print "Send Private Msg:%s Error!"%msg

#get one page of to user's replies
def getPage(user,sn,since="",page=1):
    auth=base64.b64encode(user+":"+sn)
    auth='Basic '+auth
    result = urlfetch.fetch(url="http://api.fanfou.com/statuses/replies.xml?since_id=%s&page=%d" % (since,int(page)),headers={'Authorization':auth})

    if result.status_code == 200:
        return result.content
    else:
        return False

#parse replies
#this is a private function used only by parse.
def parseMsg(msg,send_time):
    #the msg is formated as: "@... d[pq] \d+ \w+"
    #return tuple (d,p,q,time,content), the first 3 are boolean type; time :integer;content:task
    match = re.search(r"@\S+\s+(?P\w+)\s+(?P
2009年6月19日00:50
  • 2009年6月19日01:43 | #1

    支持下老大,这创意太棒了!

  • 布丁丁丁
    2009年6月19日01:48 | #2

    目前见过的第一个GAE应用,感觉很神奇,顺便忽然对python产生兴趣。

  • 2009年6月19日05:31 | #3

    python代码写出来是最整齐的。
    python的语法(数据结构)有意思。
    google支持python。

  • 2009年6月19日05:32 | #4

    呵呵。

发表评论

XHTML: 您可以使用这些标签: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">