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