toodledo 1.3.5 → 1.3.8
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +14 -0
- data/{README.txt → README.md} +61 -48
- data/Rakefile +60 -18
- data/lib/toodledo.rb +5 -4
- data/lib/toodledo/command_line/client.rb +893 -840
- data/lib/toodledo/command_line/parser_helper.rb +24 -1
- data/lib/toodledo/command_line/task_formatter.rb +174 -150
- data/lib/toodledo/priority.rb +1 -0
- data/lib/toodledo/repeat.rb +2 -0
- data/lib/toodledo/server_error.rb +17 -0
- data/lib/toodledo/session.rb +53 -18
- data/lib/toodledo/status.rb +37 -35
- data/lib/toodledo/task.rb +8 -3
- data/lib/toodledo/version.rb +11 -0
- data/test/client_test.rb +60 -12
- data/test/helper.rb +11 -0
- data/test/parser_helper_test.rb +36 -6
- data/test/session_test.rb +221 -39
- data/test/toodledo_functional_test.rb +33 -7
- data/toodledo.gemspec +97 -0
- metadata +35 -60
- data/Manifest.txt +0 -41
- data/lib/toodledo/item_not_found_error.rb +0 -8
@@ -9,6 +9,7 @@ module Toodledo
|
|
9
9
|
#
|
10
10
|
module ParserHelper
|
11
11
|
|
12
|
+
# TODO These regexps are highly repetitive. Refactor
|
12
13
|
FOLDER_REGEXP = /\*((\w+)|\[(.*?)\])/
|
13
14
|
|
14
15
|
GOAL_REGEXP = /\^((\w+)|\[(.*?)\])/
|
@@ -17,6 +18,10 @@ module Toodledo
|
|
17
18
|
|
18
19
|
PRIORITY_REGEXP = /!(top|high|medium|low|negative)/
|
19
20
|
|
21
|
+
DATE_REGEXP = /\#(([^\[]\S*)|\[(.*?)\])/
|
22
|
+
|
23
|
+
TAGS_REGEXP = /\%((\w+)|\[(.*?)\])/
|
24
|
+
|
20
25
|
# Note that level must exist at the beginning of the line
|
21
26
|
LEVEL_REGEXP = /^(life|medium|short)/
|
22
27
|
|
@@ -25,7 +30,9 @@ module Toodledo
|
|
25
30
|
FOLDER_REGEXP,
|
26
31
|
GOAL_REGEXP,
|
27
32
|
CONTEXT_REGEXP,
|
28
|
-
PRIORITY_REGEXP
|
33
|
+
PRIORITY_REGEXP,
|
34
|
+
DATE_REGEXP,
|
35
|
+
TAGS_REGEXP
|
29
36
|
]
|
30
37
|
|
31
38
|
# Parses a context in the format @Context or @[Spaced Context]
|
@@ -48,9 +55,25 @@ module Toodledo
|
|
48
55
|
return match_data if (match_data == nil)
|
49
56
|
return strip_brackets(match_data[1])
|
50
57
|
end
|
58
|
+
|
59
|
+
# Parses a date in the format #[2011-03-17]
|
60
|
+
def parse_date(input)
|
61
|
+
match_data = DATE_REGEXP.match(input)
|
62
|
+
return match_data if (match_data == nil)
|
63
|
+
return strip_brackets(match_data[1])
|
64
|
+
end
|
65
|
+
|
66
|
+
# Parses a list of tags in the format %[tag1 tag2 tag3]
|
67
|
+
# TODO Allow %tag1, tag2, tag3 ? (This is the format Toodledo's Twitter client uses)
|
68
|
+
def parse_tag(input)
|
69
|
+
match_data = TAGS_REGEXP.match(input)
|
70
|
+
return match_data if (match_data == nil)
|
71
|
+
return strip_brackets(match_data[1]).split(/\s+/)
|
72
|
+
end
|
51
73
|
|
52
74
|
# Parses priority in the format !priority (top, high, medium, low,
|
53
75
|
# negative)
|
76
|
+
# TODO Refactor using data-driven design
|
54
77
|
def parse_priority(input)
|
55
78
|
match_data = PRIORITY_REGEXP.match(input)
|
56
79
|
if (match_data == nil)
|
@@ -1,151 +1,175 @@
|
|
1
|
-
|
2
|
-
module Toodledo
|
3
|
-
module CommandLine
|
4
|
-
class TaskFormatter
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
if (task.
|
69
|
-
msg += "
|
70
|
-
end
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
when
|
126
|
-
|
127
|
-
when
|
128
|
-
|
129
|
-
when
|
130
|
-
|
131
|
-
when
|
132
|
-
|
133
|
-
when
|
134
|
-
|
135
|
-
when
|
136
|
-
|
137
|
-
when
|
138
|
-
|
139
|
-
|
140
|
-
'
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
1
|
+
|
2
|
+
module Toodledo
|
3
|
+
module CommandLine
|
4
|
+
class TaskFormatter
|
5
|
+
|
6
|
+
DUEDATE_BY = 0
|
7
|
+
DUEDATE_ON = 1
|
8
|
+
DUEDATE_AFTER = 2
|
9
|
+
DUEDATE_OPTIONALLY = 3
|
10
|
+
|
11
|
+
# Formats the task for a command line.
|
12
|
+
def format(task)
|
13
|
+
fancyp = '!' + readable_priority(task.priority)
|
14
|
+
|
15
|
+
msg = "<#{task.server_id}> -- #{fancyp}"
|
16
|
+
|
17
|
+
# TODO Only include [ ] if needed
|
18
|
+
if (task.folder != Folder::NO_FOLDER)
|
19
|
+
msg += " *[#{task.folder.name}]"
|
20
|
+
end
|
21
|
+
|
22
|
+
if (task.context != Context::NO_CONTEXT)
|
23
|
+
msg += " @[#{task.context.name}]"
|
24
|
+
end
|
25
|
+
|
26
|
+
if (task.goal != Goal::NO_GOAL)
|
27
|
+
msg += " ^[#{task.goal.name}]"
|
28
|
+
end
|
29
|
+
|
30
|
+
if (task.repeat != Repeat::NONE)
|
31
|
+
msg += " repeat[#{readable_repeat(task.repeat)}]"
|
32
|
+
end
|
33
|
+
|
34
|
+
if (task.duedate != nil)
|
35
|
+
fmt = '%m/%d/%Y %I:%M %p'
|
36
|
+
msg += " #[#{readable_duedatemodifier(task.duedatemodifier)}#{task.duedate.strftime(fmt)}]"
|
37
|
+
end
|
38
|
+
|
39
|
+
if (task.startdate != nil)
|
40
|
+
fmt = '%m/%d/%Y'
|
41
|
+
msg += " startdate[#{task.startdate.strftime(fmt)}]"
|
42
|
+
end
|
43
|
+
|
44
|
+
if (task.status != Status::NONE)
|
45
|
+
msg += " status[#{readable_status(task.status)}]"
|
46
|
+
end
|
47
|
+
|
48
|
+
if (task.star)
|
49
|
+
msg += " starred"
|
50
|
+
end
|
51
|
+
|
52
|
+
if (task.tag != nil)
|
53
|
+
msg += " %[#{task.tag}]"
|
54
|
+
end
|
55
|
+
|
56
|
+
if (task.parent_id != nil)
|
57
|
+
msg += " parent[#{task.parent.title}]"
|
58
|
+
end
|
59
|
+
|
60
|
+
if (task.length != nil)
|
61
|
+
msg += " length[#{task.length}]"
|
62
|
+
end
|
63
|
+
|
64
|
+
if (task.timer != nil)
|
65
|
+
msg += " timer[#{task.timer}]"
|
66
|
+
end
|
67
|
+
|
68
|
+
if (task.num_children != nil && task.num_children > 0)
|
69
|
+
msg += " children[#{task.num_children}]"
|
70
|
+
end
|
71
|
+
|
72
|
+
msg += " #{task.title}"
|
73
|
+
|
74
|
+
if (task.note != nil)
|
75
|
+
msg += "\n #{task.note}"
|
76
|
+
end
|
77
|
+
|
78
|
+
return msg
|
79
|
+
end
|
80
|
+
|
81
|
+
# TODO Refactor using symbols -- so much simpler to convert
|
82
|
+
def readable_priority(priority)
|
83
|
+
case priority
|
84
|
+
when Priority::TOP
|
85
|
+
return 'top'
|
86
|
+
when Priority::HIGH
|
87
|
+
return 'high'
|
88
|
+
when Priority::MEDIUM
|
89
|
+
return 'medium'
|
90
|
+
when Priority::LOW
|
91
|
+
return 'low'
|
92
|
+
when Priority::NEGATIVE
|
93
|
+
return 'negative'
|
94
|
+
else
|
95
|
+
return ''
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def readable_duedatemodifier(duedate_modifier)
|
100
|
+
# The modifier is passed in as [0..3] but may come back as
|
101
|
+
# <duedate modifier='?'>2011-06-30</duedate>
|
102
|
+
case duedate_modifier
|
103
|
+
when DUEDATE_BY then
|
104
|
+
return ''
|
105
|
+
when DUEDATE_ON then
|
106
|
+
return '='
|
107
|
+
when DUEDATE_AFTER then
|
108
|
+
return '>'
|
109
|
+
when DUEDATE_OPTIONALLY then
|
110
|
+
return '?'
|
111
|
+
else
|
112
|
+
return duedate_modifier
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
#
|
117
|
+
# Returns a string matching the numeric repeat code.
|
118
|
+
#
|
119
|
+
def readable_repeat(repeat)
|
120
|
+
case repeat
|
121
|
+
when Repeat::NONE
|
122
|
+
''
|
123
|
+
when Repeat::WEEKLY
|
124
|
+
"weekly"
|
125
|
+
when Repeat::MONTHLY
|
126
|
+
"monthly"
|
127
|
+
when Repeat::YEARLY
|
128
|
+
"yearly"
|
129
|
+
when Repeat::DAILY
|
130
|
+
"daily"
|
131
|
+
when Repeat::BIWEEKLY
|
132
|
+
"biweekly"
|
133
|
+
when Repeat::BIMONTHLY
|
134
|
+
"bimonthly"
|
135
|
+
when Repeat::SEMIANNUALLY
|
136
|
+
"semiannually"
|
137
|
+
when Repeat::QUARTERLY
|
138
|
+
"quarterly"
|
139
|
+
else
|
140
|
+
''
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
#
|
145
|
+
# Return a readable status given the numeric code.
|
146
|
+
#
|
147
|
+
def readable_status(status)
|
148
|
+
case status
|
149
|
+
when Status::NONE
|
150
|
+
'none'
|
151
|
+
when Status::NEXT_ACTION
|
152
|
+
'Next Action'
|
153
|
+
when Status::ACTIVE
|
154
|
+
'Active'
|
155
|
+
when Status::PLANNING
|
156
|
+
'Planning'
|
157
|
+
when Status::DELEGATED
|
158
|
+
'Delegated'
|
159
|
+
when Status::WAITING
|
160
|
+
'Waiting'
|
161
|
+
when Status::HOLD
|
162
|
+
'Hold'
|
163
|
+
when Status::POSTPONED
|
164
|
+
'Postponed'
|
165
|
+
when Status::SOMEDAY
|
166
|
+
'Someday'
|
167
|
+
when Status::CANCELLED
|
168
|
+
'Cancelled'
|
169
|
+
when Status::REFERENCE
|
170
|
+
'Reference'
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
151
175
|
end
|
data/lib/toodledo/priority.rb
CHANGED
data/lib/toodledo/repeat.rb
CHANGED
@@ -4,6 +4,7 @@
|
|
4
4
|
module Toodledo
|
5
5
|
class Repeat
|
6
6
|
|
7
|
+
# TODO Refactor
|
7
8
|
NONE = 0
|
8
9
|
WEEKLY = 1
|
9
10
|
MONTHLY = 2
|
@@ -32,6 +33,7 @@ module Toodledo
|
|
32
33
|
REPEAT_ARRAY.each{|value| yield(value)}
|
33
34
|
end
|
34
35
|
|
36
|
+
# TODO replace with include?
|
35
37
|
def self.valid?(input)
|
36
38
|
for repeat in REPEAT_ARRAY
|
37
39
|
if (repeat == input)
|
@@ -8,10 +8,27 @@ module Toodledo
|
|
8
8
|
|
9
9
|
end
|
10
10
|
|
11
|
+
#
|
12
|
+
# Thrown when a call to a server returns 'Invalid ID number'
|
13
|
+
#
|
14
|
+
class ItemNotFoundError < ServerError
|
15
|
+
|
16
|
+
end
|
17
|
+
|
11
18
|
# Thrown when the key is invalid (usually because we're using an old key or
|
12
19
|
# the expiration timed out for some reason)
|
13
20
|
class InvalidKeyError < ServerError
|
14
21
|
|
15
22
|
end
|
16
23
|
|
24
|
+
# Thrown when no key is specified at all.
|
25
|
+
class NoKeySpecifiedError < ServerError
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
# Thrown when too many requests have been made.
|
30
|
+
class ExcessiveTokenRequestsError < ServerError
|
31
|
+
|
32
|
+
end
|
33
|
+
|
17
34
|
end
|
data/lib/toodledo/session.rb
CHANGED
@@ -17,6 +17,11 @@ module Toodledo
|
|
17
17
|
#
|
18
18
|
class Session
|
19
19
|
|
20
|
+
INVALID_ID_MESSAGE = 'Invalid ID number'
|
21
|
+
INVALID_KEY_MESSAGE = 'key did not validate'
|
22
|
+
NO_KEY_SPECIFIED_MESSAGE = 'No Key Specified'
|
23
|
+
EXCESSIVE_TOKEN_MESSAGE = 'Excessive API token requests over the last 1 hour. This user is temporarily blocked.'
|
24
|
+
|
20
25
|
DEFAULT_API_URL = 'http://www.toodledo.com/api.php'
|
21
26
|
|
22
27
|
USER_AGENT = "Ruby/#{Toodledo::VERSION} (#{RUBY_PLATFORM})"
|
@@ -27,8 +32,8 @@ module Toodledo
|
|
27
32
|
'Keep-Alive' => '300'
|
28
33
|
}
|
29
34
|
|
30
|
-
# Make
|
31
|
-
FILE_EXPIRATION_TIME_IN_SECS = (60 * 60 * 4)
|
35
|
+
# Make file expiration be 4 hours.
|
36
|
+
FILE_EXPIRATION_TIME_IN_SECS = (60 * 60 * 4)
|
32
37
|
|
33
38
|
DATE_FORMAT = '%Y-%m-%d'
|
34
39
|
|
@@ -67,7 +72,7 @@ module Toodledo
|
|
67
72
|
return Digest::MD5.hexdigest(input_string)
|
68
73
|
end
|
69
74
|
|
70
|
-
# Connects to the server, asking for a new key that's good for
|
75
|
+
# Connects to the server, asking for a new key that's good for four hours.
|
71
76
|
# Optionally takes a base URL as a parameter. Defaults to DEFAULT_API_URL.
|
72
77
|
def connect(base_url = DEFAULT_API_URL, proxy = nil)
|
73
78
|
logger.debug("connect(#{base_url}, #{proxy.inspect})") if logger
|
@@ -105,10 +110,12 @@ module Toodledo
|
|
105
110
|
def disconnect()
|
106
111
|
logger.debug("disconnect()") if logger
|
107
112
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
113
|
+
if expired?
|
114
|
+
token_path = get_token_file(user_id)
|
115
|
+
if token_path
|
116
|
+
logger.debug("deleting token path(#{token_path})") if logger
|
117
|
+
File.delete(token_path)
|
118
|
+
end
|
112
119
|
end
|
113
120
|
|
114
121
|
@key = nil
|
@@ -126,10 +133,11 @@ module Toodledo
|
|
126
133
|
|
127
134
|
# Returns true if the session has expired.
|
128
135
|
def expired?
|
136
|
+
logger.debug("Expiration time #{@expiration_time} ") if logger
|
129
137
|
current_time = Time.now
|
130
138
|
has_expired = (@expiration_time != nil) && (current_time > @expiration_time)
|
131
139
|
if (has_expired)
|
132
|
-
logger.debug("#{@expiration_time} > #{current_time}, expired == true") if logger
|
140
|
+
logger.debug("Expiration time #{@expiration_time} > current time #{current_time}, expired == true") if logger
|
133
141
|
end
|
134
142
|
has_expired
|
135
143
|
end
|
@@ -240,21 +248,22 @@ module Toodledo
|
|
240
248
|
if (root_node.name == 'error')
|
241
249
|
error_text = root_node.text
|
242
250
|
case error_text
|
243
|
-
when
|
251
|
+
when INVALID_ID_MESSAGE then
|
244
252
|
raise Toodledo::ItemNotFoundError.new(error_text)
|
245
|
-
when
|
246
|
-
|
253
|
+
when INVALID_KEY_MESSAGE then
|
254
|
+
disconnect()
|
255
|
+
raise Toodledo::InvalidKeyError.new(error_text)
|
256
|
+
when NO_KEY_SPECIFIED_MESSAGE then
|
257
|
+
disconnect()
|
258
|
+
raise Toodledo::NoKeySpecifiedError.new(error_text)
|
259
|
+
when EXCESSIVE_TOKEN_MESSAGE
|
260
|
+
disconnect()
|
261
|
+
raise Toodledo::ExcessiveTokenRequestsError.new(error_text)
|
247
262
|
else
|
248
263
|
raise Toodledo::ServerError.new(error_text)
|
249
264
|
end
|
250
265
|
end
|
251
266
|
|
252
|
-
if (retry_error)
|
253
|
-
logger.debug("call(#{method}): invalid key, reconnecting") if logger
|
254
|
-
reconnect(@base_url, @proxy);
|
255
|
-
root_node = call(method, params);
|
256
|
-
end
|
257
|
-
|
258
267
|
return root_node
|
259
268
|
end
|
260
269
|
|
@@ -462,11 +471,14 @@ module Toodledo
|
|
462
471
|
# * star
|
463
472
|
# * status
|
464
473
|
# * startdate
|
474
|
+
# * tag
|
465
475
|
#
|
466
476
|
# Returns an array of tasks. This information is never cached.
|
467
477
|
def get_tasks(params={})
|
468
478
|
logger.debug("get_tasks(#{params.inspect})") if logger
|
469
479
|
myhash = {}
|
480
|
+
|
481
|
+
# TODO Very repetitious. Refactor
|
470
482
|
|
471
483
|
# * title : A text string up to 255 characters.
|
472
484
|
handle_string(myhash, params, :title)
|
@@ -548,6 +560,8 @@ module Toodledo
|
|
548
560
|
# * notcomp : Set to 1 to omit completed tasks. Omit variable, or set to 0
|
549
561
|
# to retrieve both completed and uncompleted tasks.
|
550
562
|
handle_boolean(myhash, params, :notcomp)
|
563
|
+
|
564
|
+
handle_tag(myhash, params)
|
551
565
|
|
552
566
|
result = call('getTasks', myhash, @key)
|
553
567
|
tasks = []
|
@@ -587,6 +601,7 @@ module Toodledo
|
|
587
601
|
# :bimonthly, :semiannually, :quarterly }
|
588
602
|
# length: a Number, number of minutes
|
589
603
|
# priority: one of { :negative, :low, :medium, :high, :top }
|
604
|
+
# tag: an Array of strings
|
590
605
|
#
|
591
606
|
# Returns: the id of the added task as a String.
|
592
607
|
def add_task(title, params={})
|
@@ -625,6 +640,8 @@ module Toodledo
|
|
625
640
|
# priority use the map to change from the symbol to the raw numeric value.
|
626
641
|
handle_priority(myhash, params)
|
627
642
|
|
643
|
+
handle_tag(myhash, params)
|
644
|
+
|
628
645
|
# Handle the star.
|
629
646
|
handle_boolean(myhash, params, :star)
|
630
647
|
|
@@ -653,6 +670,7 @@ module Toodledo
|
|
653
670
|
# * length : An integer representing the number of minutes that the task will take to complete.
|
654
671
|
# * priority : Use the PRIORITY_MAP with the relevant symbol here.
|
655
672
|
# * note : A text string.
|
673
|
+
# * tag: An Array of Strings (tags)
|
656
674
|
def edit_task(id, params = {})
|
657
675
|
logger.debug("edit_task(#{id}, #{params.inspect})") if logger
|
658
676
|
raise "Nil id" if (id == nil)
|
@@ -691,6 +709,8 @@ module Toodledo
|
|
691
709
|
|
692
710
|
# priority use the map to change from the symbol to the raw numeric value.
|
693
711
|
handle_priority(myhash, params)
|
712
|
+
|
713
|
+
handle_tag(myhash, params)
|
694
714
|
|
695
715
|
handle_string(myhash, params, :note)
|
696
716
|
|
@@ -1075,7 +1095,7 @@ module Toodledo
|
|
1075
1095
|
def handle_number(myhash, params, symbol)
|
1076
1096
|
value = params[symbol]
|
1077
1097
|
if (value != nil)
|
1078
|
-
if (value.kind_of?
|
1098
|
+
if (value.kind_of? Integer)
|
1079
1099
|
myhash.merge!({ symbol => value.to_s})
|
1080
1100
|
end
|
1081
1101
|
end
|
@@ -1122,6 +1142,21 @@ module Toodledo
|
|
1122
1142
|
myhash.merge!({ symbol => value })
|
1123
1143
|
end
|
1124
1144
|
|
1145
|
+
|
1146
|
+
def handle_tag(myhash, params)
|
1147
|
+
value = params[:tag]
|
1148
|
+
if (value == nil)
|
1149
|
+
return
|
1150
|
+
end
|
1151
|
+
|
1152
|
+
case value
|
1153
|
+
when Array
|
1154
|
+
value = value.join(' ')
|
1155
|
+
end
|
1156
|
+
|
1157
|
+
myhash.merge!({ :tag => value })
|
1158
|
+
end
|
1159
|
+
|
1125
1160
|
def handle_time(myhash, params, symbol)
|
1126
1161
|
value = params[symbol]
|
1127
1162
|
if (value == nil)
|