Quellcode durchsuchen

Update Dark Sky plugin for new API

This one got a lot more verbose, but I like it more too.  The caching
and formatting methods were moved to a base Handler class, and
individual commands subclass this using its methods as needed.  The
"hoos your weather provider" command doesn't even update the cache
anymore, which is nice.
Clara Hobbs vor 6 Jahren
Ursprung
Commit
654d386e45
1 geänderte Dateien mit 135 neuen und 69 gelöschten Zeilen
  1. 135
    69
      kayleevc/plugins/darksky.py

+ 135
- 69
kayleevc/plugins/darksky.py Datei anzeigen

@@ -30,7 +30,7 @@ import time
30 30
 
31 31
 import requests
32 32
 
33
-from .pluginbase import PluginBase
33
+from . import PluginBase, Handler
34 34
 
35 35
 
36 36
 class Plugin(PluginBase):
@@ -56,51 +56,73 @@ class Plugin(PluginBase):
56 56
             self._temp_precision = 0
57 57
 
58 58
         self.commands = {
59
-            'whats the temperature': self._temperature,
60
-            'whats todays low': self._todays_low,
61
-            'whats todays high': self._todays_high,
62
-            'whats tomorrows high': self._tomorrows_high,
63
-            'whats the humidity': self._relative_humidity,
64
-            'whats the weather': self._current_conditions,
65
-            'whens sunset': self._sunset_time,
66
-            'hoos your weather provider': self._provider_credits
59
+            'whats the temperature': DarkSkyTemperatureHandler,
60
+            'whats todays high': DarkSkyTodaysHighHandler,
61
+            'whats todays low': DarkSkyTodaysLowHandler,
62
+            'whats tomorrows high': DarkSkyTomorrowsHighHandler,
63
+            'whats the humidity': DarkSkyHumidityHandler,
64
+            'whats the weather': DarkSkyCurrentConditionsHandler,
65
+            'whens sunset': DarkSkySunsetHandler,
66
+            'hoos your weather provider': DarkSkyProviderHandler
67 67
         }
68 68
 
69 69
         self.corpus_strings.update(self.commands)
70 70
 
71
-    def _format_temperature(self, temperature, unit='Fahrenheit'):
72
-        """Format a temperature for the TTS system"""
73
-        return '{:.{prec}f} degrees {}'.format(temperature, unit,
74
-                prec=self._temp_precision)
71
+    def get_handler(self, text):
72
+        """Return a handler if a recognized command is heard"""
73
+        if text in self.corpus_strings:
74
+            return self.commands[text](1, self._cache_filename,
75
+                    self._weather_url, self._cache_max_age,
76
+                    self._temp_precision)
77
+        else:
78
+            return None
75 79
 
76
-    def _temperature(self):
77
-        return self._format_temperature(self.cache['currently']['temperature'])
78 80
 
79
-    def _todays_low(self):
80
-        return self._format_temperature(
81
-            self.cache['daily']['data'][0]['temperatureMin'])
81
+class DarkSkyHandler(Handler):
82
+    """Base class for Dark Sky plugin handlers"""
82 83
 
83
-    def _todays_high(self):
84
-        return self._format_temperature(
85
-            self.cache['daily']['data'][0]['temperatureMax'])
84
+    def __init__(self, confidence, cache_filename, url, cache_max_age,
85
+            temp_precision):
86
+        super().__init__(confidence)
86 87
 
87
-    def _tomorrows_high(self):
88
-        return self._format_temperature(
89
-            self.cache['daily']['data'][1]['temperatureMax'])
88
+        self._cache_filename = cache_filename
89
+        self._url = url
90
+        self._cache_max_age = cache_max_age
91
+        self._temp_precision = temp_precision
90 92
 
91
-    def _relative_humidity(self):
92
-        return '{:.0f} percent'.format(
93
-            100 * self.cache['currently']['humidity'])
93
+    def _update_cache_if_stale(self):
94
+        try:
95
+            st = os.stat(self._cache_filename)
96
+        except FileNotFoundError:
97
+            # If there's no cache file, we need to get one
98
+            self._update_cache()
99
+        else:
100
+            if time.time() - st.st_mtime > self._cache_max_age:
101
+                self._update_cache()
94 102
 
95
-    def _current_conditions(self):
96
-        return '{}, {}, relative humidity {}'.format(
97
-            self.cache['currently']['summary'],
98
-            self._temperature(),
99
-            self._relative_humidity())
103
+    def _update_cache(self):
104
+        r = requests.get(self._url, stream=True)
105
+        if r.status_code == 200:
106
+            with open(self._cache_filename, 'wb') as f:
107
+                for chunk in r:
108
+                    f.write(chunk)
100 109
 
101
-    def _sunset_time(self):
102
-        # Get the time in a more useful structure
103
-        t = time.localtime(self.cache['daily']['data'][0]['sunsetTime'])
110
+    def _read_cache(self):
111
+        with open(self._cache_filename, 'r') as f:
112
+            return json.load(f)
113
+
114
+    def _format_temperature(self, temperature, unit='Fahrenheit'):
115
+        """Format a temperature for the TTS system"""
116
+        return '{:.{prec}f} degrees {}'.format(temperature, unit,
117
+                prec=self._temp_precision)
118
+
119
+    def _format_percent(self, value):
120
+        """Format a percentage value for the TTS system"""
121
+        return '{:.0f} percent'.format(100 * value)
122
+
123
+    def _format_time(self, epoch_time):
124
+        """Format a time in seconds since the epoch for the TTS system"""
125
+        t = time.localtime(epoch_time)
104 126
 
105 127
         # Format each part of the time to be pronounced nicely
106 128
         hour = time.strftime('%I', t)
@@ -121,41 +143,85 @@ class Plugin(PluginBase):
121 143
         # Put the parts together
122 144
         return '{} {} {}'.format(hour, minute, ante_post)
123 145
 
124
-    def _provider_credits(self):
125
-        return 'Powered by Dark Sky, https:// dark sky .net/ powered by/.'
146
+    def __call__(self, tts):
147
+        """Update the cache if necessary and load it"""
148
+        self._update_cache_if_stale()
149
+        self.cache = self._read_cache()
126 150
 
127
-    def _update_cache_if_stale(self):
128
-        try:
129
-            st = os.stat(self._cache_filename)
130
-        except FileNotFoundError:
131
-            # If there's no cache file, we need to get one
132
-            self._update_cache()
133
-        else:
134
-            if time.time() - st.st_mtime > self._cache_max_age:
135
-                self._update_cache()
136 151
 
137
-    def _update_cache(self):
138
-        r = requests.get(self._weather_url, stream=True)
139
-        if r.status_code == 200:
140
-            with open(self._cache_filename, 'wb') as f:
141
-                for chunk in r:
142
-                    f.write(chunk)
152
+class DarkSkyTemperatureHandler(DarkSkyHandler):
153
+    """Handler to speak the current temperature"""
143 154
 
144
-    def _read_cache(self):
145
-        with open(self._cache_filename, 'r') as f:
146
-            return json.load(f)
155
+    def __call__(self, tts):
156
+        """Speak the current temperature"""
157
+        super().__call__(tts)
158
+        tts(self._format_temperature(self.cache['currently']['temperature']))
147 159
 
148
-    def confidence(self, text):
149
-        """Return whether or not the command can be handled"""
150
-        return 1 if text in self.corpus_strings else 0
151
-
152
-    def handle(self, text):
153
-        """Speak reasonably up-to-date weather information"""
154
-        # Is there a matching command?
155
-        if self.confidence(text):
156
-            self._update_cache_if_stale()
157
-            self.cache = self._read_cache()
158
-            self.emit('tts', self.commands[text]())
159
-            return True
160
-        else:
161
-            return False
160
+
161
+class DarkSkyTodaysHighHandler(DarkSkyHandler):
162
+    """Handler to speak today's high temperature"""
163
+
164
+    def __call__(self, tts):
165
+        """Speak today's high"""
166
+        super().__call__(tts)
167
+        tts(self._format_temperature(
168
+            self.cache['daily']['data'][0]['temperatureMax']))
169
+
170
+
171
+class DarkSkyTodaysLowHandler(DarkSkyHandler):
172
+    """Handler to speak today's low temperature"""
173
+
174
+    def __call__(self, tts):
175
+        """Speak today's low"""
176
+        super().__call__(tts)
177
+        tts(self._format_temperature(
178
+            self.cache['daily']['data'][0]['temperatureMin']))
179
+
180
+
181
+class DarkSkyTomorrowsHighHandler(DarkSkyHandler):
182
+    """Handler to speak tomorrow's high temperature"""
183
+
184
+    def __call__(self, tts):
185
+        """Speak tomorrow's high"""
186
+        super().__call__(tts)
187
+        tts(self._format_temperature(
188
+            self.cache['daily']['data'][1]['temperatureMax']))
189
+
190
+
191
+class DarkSkyHumidityHandler(DarkSkyHandler):
192
+    """Handler to speak the current relative humidity"""
193
+
194
+    def __call__(self, tts):
195
+        """Speak the current relative humidity"""
196
+        super().__call__(tts)
197
+        tts(self._format_percent(self.cache['currently']['humidity']))
198
+
199
+
200
+class DarkSkyCurrentConditionsHandler(DarkSkyHandler):
201
+    """Handler to speak the current weather conditions"""
202
+
203
+    def __call__(self, tts):
204
+        """Speak the current weather conditions"""
205
+        super().__call__(tts)
206
+        tts('{}, {}, relative humidity {}'.format(
207
+            self.cache['currently']['summary'],
208
+            self._format_temperature(self.cache['currently']['temperature']),
209
+            self._format_percent(self.cache['currently']['humidity'])))
210
+
211
+
212
+class DarkSkySunsetHandler(DarkSkyHandler):
213
+    """Handler to speak the time of sunset"""
214
+
215
+    def __call__(self, tts):
216
+        """Speak the time of sunset"""
217
+        super().__call__(tts)
218
+        tts(self._format_time(self.cache['daily']['data'][0]['sunsetTime']))
219
+
220
+
221
+class DarkSkyProviderHandler(DarkSkyHandler):
222
+    """Handler to speak information about the weather provider"""
223
+
224
+    def __call__(self, tts):
225
+        """Speak information about the weather provider"""
226
+        # No need for super since this doesn't need any weather information
227
+        tts('Powered by Dark Sky, https:// dark sky .net/ powered by/.')

Laden…
Abbrechen
Speichern