Passed
Push — master ( 91488b...788cfc )
by dgw
01:45 queued 10s
created

sopel.modules.clock.f_time_zone()   A

Complexity

Conditions 3

Size

Total Lines 24
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 17
dl 0
loc 24
rs 9.55
c 0
b 0
f 0
cc 3
nop 2
1
# coding=utf-8
2
"""
3
clock.py - Sopel Clock Module
4
Copyright 2008-9, Sean B. Palmer, inamidst.com
5
Copyright 2012, Elsie Powell, embolalia.com
6
Licensed under the Eiffel Forum License 2.
7
8
https://sopel.chat
9
"""
10
from __future__ import unicode_literals, absolute_import, print_function, division
11
12
from sopel import module, tools
13
from sopel.config.types import StaticSection, ValidatedAttribute
14
from sopel.tools.time import (
15
    format_time,
16
    get_channel_timezone,
17
    get_nick_timezone,
18
    get_timezone,
19
    validate_format,
20
    validate_timezone
21
)
22
23
24
class TimeSection(StaticSection):
25
    tz = ValidatedAttribute(
26
        'tz',
27
        parse=validate_timezone,
28
        serialize=validate_timezone,
29
        default='UTC')
30
    """Default time zone (see https://sopel.chat/tz)"""
31
    time_format = ValidatedAttribute(
32
        'time_format',
33
        parse=validate_format,
34
        default='%Y-%m-%d - %T%Z')
35
    """Default time format (see http://strftime.net)"""
36
37
38
def configure(config):
39
    """
40
    | name | example | purpose |
41
    | ---- | ------- | ------- |
42
    | tz | America/Chicago | Preferred time zone (see <https://sopel.chat/tz>); defaults to UTC |
43
    | time\\_format | %Y-%m-%d - %T%Z | Preferred time format (see <http://strftime.net>) |
44
    """
45
    config.define_section('clock', TimeSection)
46
    config.clock.configure_setting(
47
        'tz', 'Preferred time zone (https://sopel.chat/tz)')
48
    config.clock.configure_setting(
49
        'time_format', 'Preferred time format (http://strftime.net)')
50
51
52
def setup(bot):
53
    bot.config.define_section('clock', TimeSection)
54
55
56
@module.commands('t', 'time')
57
@module.example('.t America/New_York')
58
@module.example('.t Exirel')
59
@module.example('.t #sopel')
60
def f_time(bot, trigger):
61
    """Return the current time.
62
63
    The command takes an optional parameter: it will try to guess if it's a
64
    nick, a channel, or a timezone (in that order).
65
66
    If it's a known nick or channel but there is no configured timezone, then
67
    it will complain. If nothing can be found, it'll complain that the argument
68
    is not a valid timezone.
69
70
    .. seealso::
71
72
        Function :func:`~sopel.tools.time.format_time` is used to format
73
        the current datetime according to the timezone (if found).
74
75
    """
76
    argument = trigger.group(2)
77
78
    if not argument:
79
        # get default timezone from nick, or sender, or bot, or UTC
80
        zone = get_timezone(
81
            bot.db, bot.config, None, trigger.nick, trigger.sender)
82
    else:
83
        # guess if the argument is a nick, a channel, or a timezone
84
        zone = None
85
        argument = argument.strip()
86
        channel_or_nick = tools.Identifier(argument)
87
88
        # first, try to get nick or channel's timezone
89
        help_prefix = bot.config.core.help_prefix
90
        if channel_or_nick.is_nick():
91
            zone = get_nick_timezone(bot.db, channel_or_nick)
92
            if zone is None and channel_or_nick in bot.users:
93
                # zone not found for a known nick: error case
94
                set_command = '%ssettz <zone>' % help_prefix
95
                if channel_or_nick != trigger.nick:
96
                    bot.say(
97
                        'Could not find a timezone for this nick. '
98
                        '%s can set a timezone with `%s`'
99
                        % (argument, set_command))
100
                else:
101
                    bot.say(
102
                        'Could not find a timezone for you. '
103
                        'You can set your timezone with `%s`'
104
                        % set_command)
105
                return
106
        else:
107
            zone = get_channel_timezone(bot.db, channel_or_nick)
108
            if zone is None and channel_or_nick in bot.channels:
109
                # zone not found for an existing channel: error case
110
                set_command = '%ssetctz <zone>' % help_prefix
111
                bot.say(
112
                    'Could not find timezone for channel %s. '
113
                    'It can be set with `.setctz <zone>`. '
114
                    '(requires OP privileges)'
115
                    % argument)
116
                return
117
118
        # then, fallback on timezone detection
119
        if zone is None:
120
            # argument not found as nick or channel timezone
121
            try:
122
                zone = validate_timezone(argument)
123
            except ValueError:
124
                bot.say('Could not find timezone "%s".' % argument)
125
                return
126
127
    time = format_time(bot.db, bot.config, zone, trigger.nick, trigger.sender)
128
    bot.say(time)
129
130
131
@module.commands('tz', 'timez')
132
@module.example('.tz America/New_York')
133
def f_time_zone(bot, trigger):
134
    """Return the current time in a timezone.
135
136
    Unlike the ``.t`` command, it requires an argument, and that argument
137
    must be a valid timezone.
138
    """
139
    argument = trigger.group(2)
140
    if not argument:
141
        bot.say('Please provide a timezone.')
142
        return
143
144
    zone = None
145
    argument = argument.strip()
146
    try:
147
        zone = validate_timezone(argument)
148
    except ValueError:
149
        bot.say(
150
            'Cannot display time: "%s" is not a valid timezone.' % argument)
151
        return
152
153
    time = format_time(bot.db, bot.config, zone, trigger.nick, trigger.sender)
154
    bot.say(time)
155
156
157
@module.commands('settz', 'settimezone')
158
@module.example('.settz America/New_York')
159
def update_user(bot, trigger):
160
    """Set your preferred timezone.
161
162
    Most timezones will work, but it's best to use one from
163
    <https://sopel.chat/tz>.
164
    """
165
    argument = trigger.group(2)
166
    if not argument:
167
        bot.reply("What timezone do you want to set? Try one from "
168
                  "https://sopel.chat/tz")
169
        return
170
171
    try:
172
        zone = validate_timezone(argument)
173
    except ValueError:
174
        bot.say(
175
            'I don\'t know that timezone. Try one from https://sopel.chat/tz')
176
        return
177
178
    bot.db.set_nick_value(trigger.nick, 'timezone', zone)
179
180
    if len(zone) < 4:
181
        bot.say(
182
            'Okay, %s, but you should use one from https://sopel.chat/tz '
183
            'if you use DST.' % trigger.nick)
184
    else:
185
        bot.reply('I now have you in the %s timezone.' % zone)
186
187
188
@module.commands('gettz', 'gettimezone')
189
@module.example('.gettz [nick]')
190
def get_user_tz(bot, trigger):
191
    """Gets a user's preferred time zone; will show yours if no user specified."""
192
    nick = trigger.group(2)
193
    if not nick:
194
        nick = trigger.nick
195
196
    nick = nick.strip()
197
    zone = get_nick_timezone(bot.db, nick)
198
199
    if zone:
200
        bot.say('%s\'s time zone is %s.' % (nick, zone))
201
    else:
202
        bot.say('%s has not set their time zone' % nick)
203
204
205
@module.commands('settimeformat', 'settf')
206
@module.example('.settf %Y-%m-%dT%T%z')
207
def update_user_format(bot, trigger):
208
    """
209
    Sets your preferred format for time. Uses the standard strftime format. You
210
    can use <http://strftime.net> or your favorite search engine to learn more.
211
    """
212
    tformat = trigger.group(2)
213
    if not tformat:
214
        bot.reply("What format do you want me to use? Try using "
215
                  "http://strftime.net to make one.")
216
        return
217
218
    tz = get_timezone(bot.db, bot.config, None, trigger.nick, trigger.sender)
219
220
    # Get old format as back-up
221
    old_format = bot.db.get_nick_value(trigger.nick, 'time_format')
222
223
    # Save the new format in the database so we can test it.
224
    bot.db.set_nick_value(trigger.nick, 'time_format', tformat)
225
226
    try:
227
        timef = format_time(db=bot.db, zone=tz, nick=trigger.nick)
228
    except Exception:  # TODO: Be specific
229
        bot.reply("That format doesn't work. Try using "
230
                  "http://strftime.net to make one.")
231
        # New format doesn't work. Revert save in database.
232
        bot.db.set_nick_value(trigger.nick, 'time_format', old_format)
233
        return
234
    bot.reply("Got it. Your time will now appear as %s. (If the "
235
              "timezone is wrong, you might try the settz command)"
236
              % timef)
237
238
239
@module.commands('gettimeformat', 'gettf')
240
@module.example('.gettf [nick]')
241
def get_user_format(bot, trigger):
242
    """Gets a user's preferred time format; will show yours if no user specified."""
243
    nick = trigger.group(2)
244
    if not nick:
245
        nick = trigger.nick
246
247
    nick = nick.strip()
248
249
    # Get old format as back-up
250
    format = bot.db.get_nick_value(nick, 'time_format')
251
252
    if format:
253
        bot.say("%s's time format: %s." % (nick, format))
254
    else:
255
        bot.say("%s hasn't set a custom time format" % nick)
256
257
258
@module.commands('setchanneltz', 'setctz')
259
@module.example('.setctz America/New_York')
260
@module.require_privilege(module.OP)
261
def update_channel(bot, trigger):
262
    """Set the preferred timezone for the channel."""
263
    argument = trigger.group(2)
264
    if not argument:
265
        bot.reply("What timezone do you want to set? Try one from "
266
                  "https://sopel.chat/tz")
267
        return
268
269
    try:
270
        zone = validate_timezone(argument)
271
    except ValueError:
272
        bot.say(
273
            'I don\'t know that timezone. Try one from https://sopel.chat/tz')
274
        return
275
276
    channel = trigger.sender
277
    bot.db.set_channel_value(channel, 'timezone', zone)
278
279
    if len(zone) < 4:
280
        bot.say(
281
            'Okay, %s, but you should use one from https://sopel.chat/tz '
282
            'if you use DST.' % trigger.nick)
283
    else:
284
        bot.reply('I now have %s in the %s timezone.' % (channel, zone))
285
286
287
@module.commands('getchanneltz', 'getctz')
288
@module.example('.getctz [channel]')
289
def get_channel_tz(bot, trigger):
290
    """
291
    Gets the channel's preferred timezone; returns the current channel's
292
    if no channel name is given.
293
    """
294
    channel = trigger.group(2)
295
    if not channel:
296
        channel = trigger.sender
297
298
    channel = channel.strip()
299
    zone = get_channel_timezone(bot.db, channel)
300
301
    if zone:
302
        bot.say('%s\'s timezone: %s' % (channel, zone))
303
    else:
304
        bot.say('%s has no preferred timezone' % channel)
305
306
307
@module.commands('setchanneltimeformat', 'setctf')
308
@module.example('.setctf %Y-%m-%dT%T%z')
309
@module.require_privilege(module.OP)
310
def update_channel_format(bot, trigger):
311
    """
312
    Sets your preferred format for time. Uses the standard strftime format. You
313
    can use <http://strftime.net> or your favorite search engine to learn more.
314
    """
315
    tformat = trigger.group(2)
316
    if not tformat:
317
        bot.reply("What format do you want me to use? Try using "
318
                  "http://strftime.net to make one.")
319
320
    tz = get_timezone(bot.db, bot.config, None, None, trigger.sender)
321
322
    # Get old format as back-up
323
    old_format = bot.db.get_channel_value(trigger.sender, 'time_format')
324
325
    # Save the new format in the database so we can test it.
326
    bot.db.set_channel_value(trigger.sender, 'time_format', tformat)
327
328
    try:
329
        timef = format_time(db=bot.db, zone=tz, channel=trigger.sender)
330
    except Exception:  # TODO: Be specific
331
        bot.reply("That format doesn't work. Try using"
332
                  " http://strftime.net to make one.")
333
        # New format doesn't work. Revert save in database.
334
        bot.db.set_channel_value(trigger.sender, 'time_format', old_format)
335
        return
336
    bot.db.set_channel_value(trigger.sender, 'time_format', tformat)
337
    bot.reply("Got it. Times in this channel  will now appear as %s "
338
              "unless a user has their own format set. (If the timezone"
339
              " is wrong, you might try the settz and channeltz "
340
              "commands)" % timef)
341
342
343
@module.commands('getchanneltimeformat', 'getctf')
344
@module.example('.getctf [channel]')
345
def get_channel_format(bot, trigger):
346
    """
347
    Gets the channel's preferred time format; will return current channel's if
348
    no channel name is given.
349
    """
350
351
    channel = trigger.group(2)
352
    if not channel:
353
        channel = trigger.sender
354
355
    channel = channel.strip()
356
357
    tformat = bot.db.get_channel_value(channel, 'time_format')
358
    if tformat:
359
        bot.say('%s\'s time format: %s' % (channel, tformat))
360
    else:
361
        bot.say('%s has no preferred time format' % channel)
362