1
#!/usr/bin/env python
2
# -*- encoding:utf8 -*-
3
4
top = "."
5
feed_title = "Gauret : photos récentes"
6
start_url = "http://aurelien.bompard.org/photos"
7
limit = 100
8
feed_author = "Aurélien Bompard"
9
10
11
import sys, os, datetime, cgi, ConfigParser
12
13
if len(sys.argv) > 1:
14
    top = sys.argv[1]
15
16
use_exif = True
17
try:
18
    import PIL.Image, PIL.ExifTags
19
except ImportError:
20
    use_exif = False
21
    print "Warning: PIL is not installed, no EXIF info will be used"
22
23
24
files = []
25
for dirpath, dirnames, filenames in os.walk(top):
26
    # exclude directories starting with "_"
27
    for i, d in enumerate(dirnames):
28
        if d.startswith("_"):
29
            del dirnames[i]
30
    for name in filenames:
31
        # only include jpg images and videos
32
        if name.lower().endswith(".jpg") \
33
                or name.lower().endswith(".flv") \
34
                or name.lower().endswith(".avi"):
35
            files.append(os.path.join(dirpath, name))
36
37
metadata = {"mtimes": {}, "sizes": {}}
38
for f in files:
39
    stat = os.stat(f)
40
    metadata["mtimes"][f] = stat.st_mtime
41
    metadata["sizes"][f] = stat.st_size
42
43
def get_mtime(f):
44
    return metadata["mtimes"][f]
45
46
files.sort( key=get_mtime, reverse=True )
47
files = files[:limit]
48
49
output = """<?xml version="1.0" encoding="utf-8" standalone="yes"?>
50
<feed xmlns="http://www.w3.org/2005/Atom"
51
      xmlns:dc="http://purl.org/dc/elements/1.1/" >
52
53
	<title>%(title)s</title>
54
	<link rel="self" href="%(url)s/_atom.xml" />
55
	<link rel="alternate" type="text/html" href="%(url)s"/>
56
	<id>%(url)s</id>
57
    <updated>%(time)sZ</updated>
58
    <generator uri="http://aurelien.bompard.org/site/Mon-afficheur-de-photos-par-le-web">Photos-Index</generator>
59
	<author>
60
		<name>%(author)s</name>
61
		<uri>%(url)s</uri>
62
	</author>
63
""" % { "title": feed_title,
64
        "url": start_url,
65
        "time": datetime.datetime.now().isoformat(),
66
        "author": cgi.escape(feed_author, quote=True),
67
      }
68
69
for f in files:
70
    relpath = f.replace(top,"")
71
    url = start_url+relpath
72
    url_sb = start_url+os.path.dirname(relpath)+"/?name="+os.path.basename(f)
73
    title = os.path.basename(f)
74
    author = None
75
    dir_name = os.path.basename(os.path.dirname(f))
76
    thumb = os.path.join( os.path.dirname(url), "_thumbs", os.path.basename(f)[:-4]+".jpg" )
77
    # Read _infos.ini file
78
    infos_file = os.path.join(os.path.dirname(f), "_infos.ini")
79
    if os.path.exists(infos_file):
80
        infos = ConfigParser.ConfigParser()
81
        infos.read(infos_file)
82
        if infos.has_option(os.path.basename(f), "title"):
83
            title = infos.get(os.path.basename(f), "title").strip('"')
84
        if infos.has_option(os.path.basename(f), "author"):
85
            author = infos.get(os.path.basename(f), "author").strip('"')
86
        if infos.has_option("general", "title"):
87
            dir_name = infos.get("general", "title").strip('"')
88
    # Author
89
    if author is None and dir_name.startswith("Photos de "):
90
        author = dir_name[10:]
91
    if author is None and dir_name.startswith("Photos d'"):
92
        author = dir_name[9:]
93
    if author is None:
94
        author = feed_author
95
    # Is it protected ? Only embed the thumbnail if it's not
96
    protected = False
97
    subdirs = os.path.dirname(relpath[1:]).split("/")
98
    for i in range(len(subdirs)):
99
        subdir = os.path.join(top,"/".join(subdirs[:i+1]))
100
        if os.path.exists(os.path.join(subdir, ".htaccess")):
101
            protected = True
102
    # Summary
103
    if protected:
104
        content = '<a href="%s">%s</a>' % (url_sb, title)
105
    else: # it's not protected, embed the thumbnail
106
        content = '<a href="%s"><img style="border:none" src="%s" /></a>' % (url_sb, thumb)
107
    content += " (dans %s)" % os.path.dirname(relpath)
108
    # MIME type
109
    if f.endswith(".jpg"):
110
        ftype = "image/jpeg"
111
    elif f.endswith(".flv"):
112
        ftype = "video/x-flv"
113
    elif f.endswith(".avi"):
114
        ftype = "video/x-msvideo"
115
    # Make XML
116
    output += """
117
	<entry>
118
		<title>%(title)s</title>
119
		<link rel="alternate" type="text/html" href="%(url_sb)s"/>
120
		<id>%(url)s</id>
121
		<updated>%(mtime)sZ</updated>
122
		<content type="html">%(content)s</content>
123
		<link rel="enclosure" type="%(type)s" length="%(size)s" href="%(url)s"/>
124
""" % {"title": cgi.escape(title, quote=True),
125
       "url_sb": url_sb,
126
       "url": url,
127
       "mtime": datetime.datetime.fromtimestamp(metadata["mtimes"][f]).isoformat(),
128
       "content": cgi.escape(content, quote=True),
129
       "size": metadata["sizes"][f],
130
       "type": ftype,
131
      }
132
    output += """		<author>
133
			<name>"""+cgi.escape(author, quote=True)+"""</name>
134
		</author>
135
"""
136
    if use_exif:
137
        try:
138
            exif = PIL.Image.open(f)._getexif()
139
        except (IOError, KeyError):
140
            exif = None
141
        if exif is not None:
142
            try:
143
                exif_dt = exif[0x0132] # DateTime
144
                exif_dt = datetime.datetime(int(exif_dt[0:4]),int(exif_dt[5:7]),int(exif_dt[8:10]),
145
                                            int(exif_dt[11:13]),int(exif_dt[14:16]),int(exif_dt[17:19]))
146
                output += """		<dc:date.Taken>"""+exif_dt.isoformat()+"""Z</dc:date.Taken>"""
147
            except KeyError, e:
148
                print "Warning: No EXIF DateTime info on", title
149
            except ValueError, e:
150
                print "Warning: EXIF data is wrong:", e, "on", exif_dt, "("+title+")"
151
        else:
152
            print "Warning: Can't extract EXIF data from", f
153
    output += """
154
	</entry>
155
"""
156
output += "</feed>\n"
157
158
out = open(os.path.join(top,"_atom.xml"), "w")
159
out.write(output)
160
out.close()