| 1 |
#!/usr/bin/env python |
| 2 |
# vim: set fileencoding=utf-8 tabstop=4 shiftwidth=4 expandtab smartindent: |
| 3 |
u""" |
| 4 |
|
| 5 |
Backup Delicious |
| 6 |
---------------- |
| 7 |
|
| 8 |
Backs up the bookmarks stored on Delicious.com into an XML file. |
| 9 |
|
| 10 |
.. :Authors: |
| 11 |
Aurélien Bompard <aurelien@bompard.org> <http://aurelien.bompard.org> |
| 12 |
|
| 13 |
.. :License: |
| 14 |
GNU GPL v3 or later |
| 15 |
""" |
| 16 |
|
| 17 |
import os |
| 18 |
import sys |
| 19 |
import optparse |
| 20 |
import urllib2 |
| 21 |
from xml.etree import ElementTree as etree |
| 22 |
import datetime |
| 23 |
|
| 24 |
backup = os.path.expanduser("~/tmp/bookmarks.xml") |
| 25 |
|
| 26 |
def setup_url_opener(username, password): |
| 27 |
auth_handler = urllib2.HTTPBasicAuthHandler() |
| 28 |
auth_handler.add_password(realm="del.icio.us API", |
| 29 |
uri='https://api.del.icio.us/v1/posts/', |
| 30 |
user=username, passwd=password) |
| 31 |
opener = urllib2.build_opener(auth_handler) |
| 32 |
opener.addheaders = [('User-agent', 'Mozilla/5.0')] |
| 33 |
urllib2.install_opener(opener) |
| 34 |
|
| 35 |
def get_update_time(): |
| 36 |
update_page = urllib2.urlopen("https://api.del.icio.us/v1/posts/update") |
| 37 |
update = etree.parse(update_page) |
| 38 |
update_page.close() |
| 39 |
update_time = datetime.datetime.strptime( |
| 40 |
update.getroot().get("time"), |
| 41 |
"%Y-%m-%dT%H:%M:%SZ") |
| 42 |
return update_time |
| 43 |
|
| 44 |
def get_backup_time(backup_file): |
| 45 |
if not os.path.exists(backup_file): |
| 46 |
return datetime.datetime(1970,1,1,0,0,0) |
| 47 |
statinfo = os.stat(backup_file) |
| 48 |
return datetime.datetime.fromtimestamp(statinfo.st_mtime) |
| 49 |
|
| 50 |
def backup_delicious(backup_file): |
| 51 |
backup_file = open(backup_file, "w") |
| 52 |
bookmarks_page = urllib2.urlopen("https://api.del.icio.us/v1/posts/all") |
| 53 |
backup_file.write(bookmarks_page.read()) |
| 54 |
backup_file.close() |
| 55 |
bookmarks_page.close() |
| 56 |
|
| 57 |
def parse_opts(): |
| 58 |
parser = optparse.OptionParser() |
| 59 |
parser.add_option("-u", "--username", dest="username", |
| 60 |
help="User name on Delicious.com") |
| 61 |
parser.add_option("-p", "--password", dest="password", |
| 62 |
help="Password on Delicious.com") |
| 63 |
parser.add_option("-f", "--file", dest="backup", |
| 64 |
help="File to store the backup into") |
| 65 |
options, args = parser.parse_args() |
| 66 |
if len(args): |
| 67 |
parser.error("No arguments allowed.") |
| 68 |
if not options.username or not options.password: |
| 69 |
parser.error("You must provide credentials to Delicious.com.") |
| 70 |
if not options.backup: |
| 71 |
parser.error("You must provide a file to backup into.") |
| 72 |
return options |
| 73 |
|
| 74 |
def main(): |
| 75 |
options = parse_opts() |
| 76 |
setup_url_opener(options.username, options.password) |
| 77 |
backup_file = os.path.expanduser(options.backup) |
| 78 |
update_time = get_update_time() |
| 79 |
backup_time = get_backup_time(backup_file) |
| 80 |
|
| 81 |
if update_time > backup_time: |
| 82 |
print "Bookmarks have been updated, backing up... ", |
| 83 |
sys.stdout.flush() |
| 84 |
backup_delicious(backup_file) |
| 85 |
print "done." |
| 86 |
else: |
| 87 |
print "No update available, backup cancelled." |
| 88 |
|
| 89 |
if __name__ == "__main__": |
| 90 |
main() |