Skip to content

Instantly share code, notes, and snippets.

@seanh
Last active September 22, 2015 11:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save seanh/bf93520287a71b86567c to your computer and use it in GitHub Desktop.
Save seanh/bf93520287a71b86567c to your computer and use it in GitHub Desktop.
Copy an annotatation from one Hypothesis instance to another
#!/usr/bin/env python2.7
import argparse
import json
import requests
def get_annotation(url, id_):
return requests.get(url + "/api/annotations/" + id_).json()
def login(username, password, url):
"""Login to a Hypothesis site and return the user ID and API token.
The API token can be used in Authorization headers in subsequent requests
to the API like so:
Authorization: Bearer <api_token>
:returns: A 2-tuple (userid, api_token)
"""
# Get an XSRF-TOKEN and an unauthenticated session token from /app.
# We need these to post the login form.
response = requests.get(url + "/app")
xsrf_token = response.cookies["XSRF-TOKEN"]
unauthenticated_session_token = response.cookies["session"]
# Login, getting an authenticated session token.
response = requests.post(
url + "/app?__formid__=login",
data=json.dumps({"username": username, "password": password}),
cookies={"session": unauthenticated_session_token},
headers={"X-CSRF-TOKEN": xsrf_token})
authenticated_session_token = response.cookies["session"]
userid = response.json()['model']['userid']
# Exchange our authenticated session token for an API token.
response = requests.get(
url + "/api/token?assertion=" + xsrf_token,
cookies={"session": authenticated_session_token},
)
api_token = response.text
return (userid, api_token)
def create_annotation(username, password, url, annotation):
"""Create a new annotation using the Hypothesis API and return it."""
userid, api_token = login(username, password, url)
response = requests.post(
url + "/api/annotations",
data=json.dumps(annotation),
headers={"Authorization": "Bearer " + api_token})
return response.json()
def main():
"""Copy an annotation from one Hypothesis instance to another."""
parser = argparse.ArgumentParser(
description="Copy annotations between Hypothesis instances.\n\n"
"For example:\n\n"
" %(prog)s seanh pass 'http://hypothes.is' "
"'http://127.0.0.1:5000' 't9YqjMY2Ql6jvxQEUSRK8w'",
formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument(
"username",
help="Username of the account to use to create new annotations with "
"on the Hypothesis instance that you're copying to, for example: "
"'seanh'")
parser.add_argument(
"password",
help="Password for the given username, for example: 'pass'")
parser.add_argument(
"from_url",
help="Base URL of the Hypothesis instance that you want to copy "
"annotations from, for example: 'https://hypothes.is'")
parser.add_argument(
"to_url",
help="Base URL of the Hypothesis instance that you want to copy "
"annotations to, for example: 'http://127.0.0.1:5000'")
parser.add_argument(
"id",
help="The ID of the annotation to copy, for example: "
"'AU_0m-p0HH3C7n45IL6f'")
args = parser.parse_args()
if args.from_url.endswith("/"):
args.from_url = args.from_url[:-1]
if args.to_url.endswith("/"):
args.to_url = args.to[:-1]
print create_annotation(
args.username, args.password, args.to_url,
get_annotation(args.from_url, args.id))
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment