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()