b27a7918feba389de82897941806bda83ee6ac99
[kiosk.git] / local_photos_mirror_renderer.py
1 #!/usr/bin/env python3
2
3 import os
4 import random
5 import re
6 from typing import Dict, Set
7
8 import constants
9 import file_writer
10 import renderer
11
12
13 class local_photos_mirror_renderer(renderer.debuggable_abstaining_renderer):
14     """A renderer that uses a local mirror of Google photos"""
15
16     ALBUM_ROOT_DIR = "/var/www/kiosk/pages/images/gphotos/albums"
17
18     album_whitelist = frozenset(
19         [
20             "8-Mile Lake Hike",
21             "Bangkok and Phuket, 2003",
22             "Barn",
23             "Blue Angels... Seafair",
24             "Chihuly Glass",
25             "Dunn Gardens",
26             "East Coast 2018",
27             "Fall '17",
28             "Friends",
29             "Hiking",
30             "Key West 2019",
31             "Krakow 2009",
32             "Kubota Gardens",
33             "Las Vegas, 2017",
34             "London, 2018",
35             "Munich, July 2018",
36             "NJ 2015",
37             "Newer Alex Photos",
38             "Ohme Gardens",
39             "Olympic Sculpture Park",
40             "Prague and Munich 2019",
41             "Random",
42             "Scott and Lynn",
43             "SFO 2014",
44             "Skiing with Alex",
45             "Sonoma",
46             "Trip to California, '16",
47             "Trip to San Francisco",
48             "Trip to East Coast '16",
49             "Tuscany 2008",
50             "Yosemite 2010",
51             "Zoo",
52         ]
53     )
54
55     extension_whitelist = frozenset(
56         [
57             "jpg",
58             "gif",
59             "JPG",
60             "jpeg",
61             "GIF",
62         ]
63     )
64
65     def __init__(self, name_to_timeout_dict: Dict[str, int]) -> None:
66         super(local_photos_mirror_renderer, self).__init__(name_to_timeout_dict, False)
67         self.candidate_photos: Set[str] = set()
68
69     def debug_prefix(self) -> str:
70         return "local_photos_mirror"
71
72     def periodic_render(self, key: str) -> bool:
73         if key == "Index Photos":
74             return self.index_photos()
75         elif key == "Choose Photo":
76             return self.choose_photo()
77         else:
78             raise Exception("Unexpected operation")
79
80     def album_is_in_whitelist(self, name: str) -> bool:
81         for wlalbum in self.album_whitelist:
82             if re.search("\d+ %s" % wlalbum, name) is not None:
83                 return True
84         return False
85
86     def index_photos(self) -> bool:
87         """Walk the filesystem looking for photos in whitelisted albums and
88         keep their paths in memory.
89         """
90         for root, subdirs, files in os.walk(self.ALBUM_ROOT_DIR):
91             last_dir = root.rsplit("/", 1)[1]
92             if self.album_is_in_whitelist(last_dir):
93                 for filename in files:
94                     extension = filename.rsplit(".", 1)[1]
95                     if extension in self.extension_whitelist:
96                         photo_path = os.path.join(root, filename)
97                         photo_url = photo_path.replace(
98                             "/var/www/", f"http://{constants.hostname}/", 1
99                         )
100                         self.candidate_photos.add(photo_url)
101         return True
102
103     def choose_photo(self):
104         """Pick one of the cached URLs and build a page."""
105         if len(self.candidate_photos) == 0:
106             print("No photos!")
107             return False
108         path = random.sample(self.candidate_photos, 1)[0]
109         with file_writer.file_writer("photo_23_3600.html") as f:
110             f.write(
111                 """
112 <style>
113 body{background-color:#303030;}
114 div#time{color:#dddddd;}
115 div#date{color:#dddddd;}
116 </style>
117 <center>"""
118             )
119             f.write(
120                 f'<img src="{path}" style="display:block;max-width=800;max-height:600;width:auto;height:auto">'
121             )
122             f.write("</center>")
123         return True
124
125
126 # Test code
127 # x = local_photos_mirror_renderer({"Index Photos": (60 * 60 * 12),
128 #                                  "Choose Photo": (1)})
129 # x.index_photos()
130 # x.choose_photo()