Skip to content

Commit

Permalink
Completed script and added README
Browse files Browse the repository at this point in the history
- Also added goal_name as config parameter
  • Loading branch information
davecahill committed Jun 13, 2013
1 parent 8f9796b commit 6757904
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 65 deletions.
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
Usage
---------

Copy default_config.ini to config.ini and fill in your insighttimer.com and beeminder credentials.

Your beeminder auth token can be found at this URL when logged in:
https://www.beeminder.com/api/v1/auth_token.json

To run:
```
python beeminder.py
```

I set this up on a cron so that it runs occasionally, and posts new datapoints to beeminder if there are any.

Notes
------
beesight.py currently subtracts one from the dates it gets from beeminder,
because beeminder returns JST (Japanese Standard Time) 01:00 on (correct_day + 1)
in my timezone. If you're in another timezone, this may cause your dates
to be off by one.

103 changes: 38 additions & 65 deletions beesight.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import requests
import sys
import simplejson
import pytz
import time

# complain on config file issues
Expand All @@ -15,100 +14,78 @@
CONFIG_FILE_NAME = 'config.ini'
INSIGHT_SECTION = 'insight'
BEEMINDER_SECTION = 'beeminder'
GOAL_NAME = 'meditate'
BASE_URL= "https://www.beeminder.com/api/v1/"

GET_DATAPOINTS_URL = BASE_URL + "users/%s/goals/%s/datapoints.json?auth_token=%s"
POST_MANY_DATAPOINTS_URL = BASE_URL + "users/%s/goals/%s/datapoints/create_all.json?auth_token=%s"
POST_DATAPOINTS_URL = GET_DATAPOINTS_URL + "&timestamp=%s&value=%s"


LOGIN_URL = "https://insighttimer.com/user_session"
INSIGHT_CSV_URL = "https://insighttimer.com/users/export"

headers = {}
BASE_URL= "https://www.beeminder.com/api/v1/"
GET_DATAPOINTS_URL = BASE_URL + "users/%s/goals/%s/datapoints.json?auth_token=%s"
POST_MANY_DATAPOINTS_URL = BASE_URL + "users/%s/goals/%s/datapoints/create_all.json?auth_token=%s"
POST_DATAPOINTS_URL = GET_DATAPOINTS_URL + "&timestamp=%s&value=%s"

def get_insight_data():
config = ConfigParser.RawConfigParser()
config.read(CONFIG_FILE_NAME)
config = ConfigParser.RawConfigParser()
config.read(CONFIG_FILE_NAME)

username = config.get(INSIGHT_SECTION, "username")
password = config.get(INSIGHT_SECTION, "password")
username = config.get(INSIGHT_SECTION, "username")
password = config.get(INSIGHT_SECTION, "password")

values = {'user_session[email]' : username,
'user_session[password]' : password }
login_data = urllib.urlencode(values)
values = {'user_session[email]' : username,
'user_session[password]' : password }
login_data = urllib.urlencode(values)

# Start a session so we can have persistent cookies
session = requests.session()
# Start a session so we can have persistent cookies
session = requests.session()
r = session.post(LOGIN_URL, data=login_data)
r = session.get(INSIGHT_CSV_URL)
return r.text.split('\n')

r = session.post(LOGIN_URL, data=login_data)

r = session.get(INSIGHT_CSV_URL)

return r.text.split('\n')

def post_beeminder_data(data):
def post_beeminder_entry(entry):
config = ConfigParser.RawConfigParser()
config.read(CONFIG_FILE_NAME)

username = config.get(BEEMINDER_SECTION, "username")
auth_token = config.get(BEEMINDER_SECTION, "auth_token")


# json_headers
headers = {'content-type': 'application/json'}
values = {'datapoints' : data}
json_data = simplejson.dumps(values)
goal_name = config.get(BEEMINDER_SECTION, "goal_name")

session = requests.session()
full_url = POST_MANY_DATAPOINTS_URL % (username, GOAL_NAME, auth_token)
full_url = POST_DATAPOINTS_URL % (username, goal_name, auth_token, entry["timestamp"], entry["value"])
r = session.post(full_url)

"""
r = session.post(full_url, data=json_data) #btry w/o headers, headers=headers)
print r.url
print r.text
"""
print json_data
print "Posted entry: %s" % r.text

def get_beeminder():
config = ConfigParser.RawConfigParser()
config.read(CONFIG_FILE_NAME)

username = config.get(BEEMINDER_SECTION, "username")
auth_token = config.get(BEEMINDER_SECTION, "auth_token")
goal_name = config.get(BEEMINDER_SECTION, "goal_name")

response = urllib2.urlopen(GET_DATAPOINTS_URL % (username, GOAL_NAME, auth_token))
response = urllib2.urlopen(GET_DATAPOINTS_URL % (username, goal_name, auth_token))
the_page = response.read()
return the_page

def beeminder_to_one_per_day(beeminder_output):
bm = simplejson.loads(beeminder_output)

print bm

s = {}

# skip first two header lines
for entry in bm:
tz = pytz.timezone('Asia/Tokyo')
ts = entry['timestamp']
print ts
dt = datetime.datetime.fromtimestamp(ts)
print "bmdt", dt
ld = tz.localize(dt)
d = ld.date()
print "d", d

# need to move back one dayfrom the beeminder time, because it
# pushes the day forward to 01:00 on day + 1, at least in JST
d = dt.date() - datetime.timedelta(days=1)

if not d in s:
s[d] = 1

return s.keys()


def csv_to_one_per_day(csv_lines):

print csv_lines
s = {}

# skip first two header lines
Expand All @@ -126,29 +103,25 @@ def csv_to_one_per_day(csv_lines):
return s.keys()

def date_to_jp_timestamp(dt):
tz = pytz.timezone('Asia/Tokyo')
d = datetime.datetime.combine(dt, datetime.time())
offset = tz.utcoffset(d)
ld = d - offset
return int(time.mktime(ld.timetuple()))
return int(time.mktime(d.timetuple()))

if __name__ == "__main__":

# get dates of days meditated, from insight
insight_dates = csv_to_one_per_day(get_insight_data())
print "%s days meditated according to insighttimer.com" % len(insight_dates)

# get dates of days meditated, from beeminder
beeminder_dates = beeminder_to_one_per_day(get_beeminder())
print "%s datapoints in beeminder" % len(beeminder_dates)

print "------"
print sorted(insight_dates)
print sorted(beeminder_dates)
print "------"
# get dates which beeminder doesn't know about yet
new_dates = sorted(list(set(insight_dates) - set(beeminder_dates)))

print new_dates[0]
# create beeminder-friendly datapoints
new_datapoints = [{'timestamp': date_to_jp_timestamp(d), 'value':1.0, "comment":"test"} for d in new_dates]

print new_datapoints
print "**** %s to be posted" % len(new_datapoints)

post_beeminder_data(new_datapoints[0:1])
print "posted"
print "%s datapoints to post" % len(new_datapoints)

for dp in new_datapoints:
post_beeminder_entry(dp)
8 changes: 8 additions & 0 deletions default_config.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[insight]
username=
password=

[beeminder]
username=
auth_token=
goal_name=

0 comments on commit 6757904

Please sign in to comment.