fluttrly 0.0.4 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md CHANGED
@@ -18,38 +18,62 @@ to be refactored.
18
18
 
19
19
 
20
20
  ##Usage
21
- ** List an item **
21
+
22
+ ####List an item
23
+
22
24
  #fluttrly <command> <list>
23
25
  $ fluttrly list bouverdafs
24
26
  Task => "Nothing to see here, move along" at => 02-08-2011 18:57 PM
25
27
 
26
- ** Post an item **
28
+ ####Post an item
29
+
27
30
  #fluttrly <command> <list> <message>
28
31
  $ fluttrly post bouverdafs "gem'd"
29
- $ fluttrly list bouverdafs
30
32
  Task => "gem'd" at => 02-10-2011 16:18 PM
31
33
  Task => "Nothing to see here, move along" at => 02-08-2011 18:57 PM
32
34
 
33
- ** Update a task **
35
+ ####Update a task
36
+
34
37
  #fluttrly <command> <list>
35
38
  $ fluttrly update bouverdafs
36
39
  1: Task => "gem'd" at => 02-10-2011 16:18 PM (Completed? false)
37
40
  2: Task => "Nothing to see here, move along" at => 02-08-2011 18:57 PM (Completed? false)
38
41
  Which item would you like to edit?
39
42
  1
40
- $ fluttrly list bouverdafs
41
43
  1: Task => "gem'd" at => 02-10-2011 16:18 PM (Completed? true)
42
44
  2: Task => "Nothing to see here, move along" at => 02-08-2011 18:57 PM (Completed? false)
43
45
 
44
-
46
+ ####Delete a task
47
+ #fluttrly <command> <list>
48
+ $ fluttrly delete bouverdafs
49
+ 1: Task => "Make a throwaway task for deleting" at => 05-10-2011 03:59 AM (Completed? false)
50
+ 2: Task => "write tests for test::unit" at => 05-10-2011 03:56 AM (Completed? false)
51
+ 3: Task => "Add to the README" at => 05-10-2011 03:56 AM (Completed? true)
52
+ 4: Task => "Add delete functionality" at => 05-10-2011 03:56 AM (Completed? true)
53
+ Which item would you like to delete?
54
+ 1
55
+ 1: Task => "write tests for test::unit" at => 05-10-2011 03:56 AM (Completed? false)
56
+ 2: Task => "Add to the README" at => 05-10-2011 03:56 AM (Completed? true)
57
+ 3: Task => "Add delete functionality" at => 05-10-2011 03:56 AM (Completed? true)
58
+
59
+
60
+
61
+ ##Install
62
+ Fork or download this and play with it yourself! If you want to just test
63
+ it locally:
64
+ $ bundle
65
+ $ gem build fluttrly-gem.gemspec
66
+ $ gem install fluttrly-0.0.4.gem
67
+
68
+ Or just grab the latest from rubygems.org and use it.
45
69
 
46
-
47
- ##Install
48
70
  $ gem install fluttrly
49
71
 
72
+
73
+
50
74
  ##TO DO
51
- * Tom-doc this ish
52
75
  * Removing items completely (1 or many)
53
- * Adding to locked lists :\
76
+ * Adding to locked lists
77
+ * Refactor for caching so we don't make so many http requests
54
78
 
55
79
 
data/Rakefile CHANGED
@@ -1,2 +1,13 @@
1
1
  require 'bundler'
2
+ require 'rubygems'
3
+ require 'rake'
4
+
2
5
  Bundler::GemHelper.install_tasks
6
+
7
+ task :default => :test
8
+
9
+ require 'rake/testtask'
10
+ Rake::TestTask.new(:test) do |test|
11
+ test.libs << 'lib' << 'test'
12
+ test.pattern = 'test/**/test_*.rb'
13
+ end
@@ -1,126 +1,17 @@
1
- require 'rubygems'
1
+
2
+ begin
3
+ require 'rubygems'
4
+ rescue LoadError
5
+ end
6
+
2
7
  require 'net/http'
3
8
  require 'JSON'
4
9
  require 'Time'
5
10
 
11
+ $:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
6
12
 
7
- #require 'fluttrly-gem/command'
8
- module Fluttrly
9
- # Your code goes here...
10
- class Command
11
- class << self
12
- def execute(*args)
13
- command = args.shift
14
- list = args.shift
15
- message = args.empty? ? nil : args.join(' ')
16
-
17
- parse_arguments(command, list, message)
18
-
19
- end
20
-
21
- def parse_arguments(command, list, message)
22
- return list(list) if command == 'list'
23
- return post(list, message) if command == 'post'
24
- return update(list) if command == 'update'
25
- end
26
-
27
- def update(list)
28
- response = form_response(list)[1]
29
- page = list(list)
30
- if page
31
- puts 'Which item would you like to edit?'
32
- num = STDIN.gets.chomp.to_i
33
- id = page[num-1]["task"]["id"]
34
- update_task(id,response)
35
- end
36
- end
37
-
38
- def list(list)
39
- response = form_response(list, true)[1]
40
- if Net::HTTPSuccess === response
41
- i = 1
42
- page = JSON.parse(response.body)
43
- page.each do |task|
44
- puts("#{i}: Task => \"#{task["task"]["content"]}\" at => #{Time.parse(task["task"]["created_at"]).strftime("%m-%d-%Y %H:%M %p")} (Completed? #{task["task"]["completed"]})")
45
- i = i+1
46
- end
47
- if page.empty?
48
- puts "Oops, that list doesn't have any items yet!"
49
- puts "Try: fluttrly post #{list} <message> first."
50
- return false
51
- end
52
- page
53
- else
54
- response.error!
55
- end
56
- end
13
+ require 'fluttrly-gem/command'
57
14
 
58
- #Posting requires getting COOKIE om nom nom and a csrf token..
59
- def post(list, message)
60
- http, response = form_response(list)
61
- if Net::HTTPSuccess === response
62
- response = post_request(list, message, response,http)
63
- else
64
- response.error!
65
- end
66
- end
67
-
68
- private
69
-
70
- def form_response(list, get=nil)
71
-
72
- #refactors are welcome here =\
73
- if get.nil?
74
- uri = URI.parse("http://fluttrly.com/#{list}")
75
- else
76
- uri = URI.parse("http://fluttrly.com/#{list}.json")
77
- end
78
-
79
- http = Net::HTTP.new(uri.host, uri.port)
80
- response = http.request(Net::HTTP::Get.new(uri.request_uri))
81
- [http, response]
82
- end
83
-
84
- def post_request(list, message, response, http)
85
- #get the csrf-token, really wanna use hpricot here but...
86
- auth_token = $1 if response.body =~ /"authenticity_token".*value="(.+)"/ or nil
87
- raise "No authenticity token found :(" if auth_token.nil?
88
-
89
- #COOKIE COOKIE COOKIE COOKIE COOKIE COOKIE
90
- cookie = response['set-cookie'].split('; ')[0]
91
-
92
- #ok ok, NOW send that post data
93
- uri = URI.parse('http://fluttrly.com/tasks.js')
94
- request = Net::HTTP::Post.new(uri.request_uri)
95
- params = {
96
- 'authenticity_token' => auth_token,
97
- 'task[name]' => "#{list}",
98
- 'task[content]' => "#{message}"
99
- }
100
- request["Cookie"] = cookie
101
- request.set_form_data(params)
102
- response = http.request(request)
103
- end
104
-
105
- def update_task(id, response)
106
- auth_token = $1 if response.body =~ /"csrf-token".*content="(.+)"/ or nil
107
- raise "No authenticity token found :(" if auth_token.nil?
108
-
109
- #COOKIE COOKIE COOKIE COOKIE COOKIE COOKIE
110
- cookie = response['set-cookie'].split('; ')[0]
111
-
112
- uri = URI.parse("http://fluttrly.com/tasks/#{id}")
113
- http = Net::HTTP.new(uri.host, uri.port)
114
- request = Net::HTTP::Put.new(uri.request_uri)
115
- params = {
116
- 'authenticity_token' => auth_token,
117
- 'completed' => "true"
118
- }
119
- request["Cookie"] = cookie
120
- request.set_form_data(params)
121
- response = http.request(request)
122
- end
15
+ module Fluttrly
123
16
 
124
- end
125
- end
126
17
  end
@@ -0,0 +1,253 @@
1
+
2
+ # Command is used to execute the basic commands for interaction with
3
+ # fluttrly.com
4
+ #
5
+ #
6
+ module Fluttrly
7
+ class Command
8
+ class << self
9
+
10
+ # Takes arguments from command line
11
+ #
12
+ # args - The list of arguments passed in. If they are
13
+ # in the wrong order, the proper command will not be
14
+ # executed correctly when passed to parse_arguments()
15
+ #
16
+ def execute(*args)
17
+ command = args.shift
18
+ list = args.shift
19
+ message = args.empty? ? nil : args.join(' ')
20
+
21
+ parse_arguments(command, list, message)
22
+ end
23
+
24
+ # Receives arguments and delegates them appropriately
25
+ #
26
+ # command - First argument used to decide what additional method
27
+ # to call.
28
+ # list - The list to use execute the command on.
29
+ # message - Used to post to a list.
30
+ #
31
+ # Returns output based on the method called.
32
+ def parse_arguments(command, list, message)
33
+ return list(list) if command == 'list' || command == 'l'
34
+ return post(list, message) if command == 'post' || command == 'p'
35
+ return update(list) if command == 'update' || command == 'c'
36
+ return delete(list) if command == 'delete' || command == 'd'
37
+ return help if command == 'help' || command == '-h'
38
+ end
39
+
40
+ # Command used to delete one or all items in a list
41
+ #
42
+ # list - List to delete items from.
43
+ # num - Number in the list to update if already known.
44
+ #
45
+ # Returns a refreshed list showing the changes
46
+ def delete(list, num=nil)
47
+ response = form_response(list)[1]
48
+ page = list(list)
49
+ if page
50
+ puts "Which item would you like to delete?"
51
+ num = STDIN.gets.chomp.to_i if num.nil?
52
+ id = page[num-1]["task"]["id"]
53
+ delete_task(id, response)
54
+ #list(list)
55
+ end
56
+ end
57
+
58
+ # Command used if wanting to mark an item to edit
59
+ #
60
+ # list - List to update
61
+ # num - Number in list to update if already known.
62
+ #
63
+ # Returns the list with its items to show the change.
64
+ def update(list, num=nil)
65
+ response = form_response(list)[1]
66
+ page = list(list)
67
+ if page
68
+ puts 'Which item would you like to edit?'
69
+ num = STDIN.gets.chomp.to_i if num.nil?
70
+ id = page[num-1]["task"]["id"]
71
+ update_task(id,response)
72
+ #list(list)
73
+ end
74
+ end
75
+
76
+ # Command used to list the items within a list
77
+ #
78
+ # list - List to show contents of.
79
+ #
80
+ # Returns a list of tasks for the given list.
81
+ def list(list)
82
+ response = form_response(list, true)[1]
83
+ if Net::HTTPSuccess === response
84
+ i = 1
85
+ page = JSON.parse(response.body)
86
+ puts ""
87
+ page.each do |task|
88
+ puts("#{i}: Task => \"#{task["task"]["content"]}\" at => #{Time.parse(task["task"]["created_at"]).strftime("%m-%d-%Y %H:%M %p")} (Completed? #{task["task"]["completed"]})")
89
+ i = i+1
90
+ end
91
+ if page.empty?
92
+ puts "Oops, that list doesn't have any items yet!"
93
+ puts "Try: fluttrly post #{list} <message> first."
94
+ return false
95
+ end
96
+ page
97
+ else
98
+ response.error!
99
+ end
100
+ end
101
+
102
+ # Used to post a message to a given list.
103
+ #
104
+ # list - List to send a message to.
105
+ # message - Message to pass to the list.
106
+ #
107
+ # Returns a newly updated list.
108
+ def post(list, message)
109
+ http, response = form_response(list)
110
+ if Net::HTTPSuccess === response
111
+ response = post_request(list, message, response,http)
112
+ else
113
+ response.error!
114
+ end
115
+ #list(list)
116
+ end
117
+
118
+ # Command used to print out some helpful hints!
119
+ #
120
+ #
121
+ # Returns nothing.
122
+ def help
123
+ text = %{
124
+ Fluttrly is a nice web app to help you collaborate to-do lists
125
+ with your friends, this is the 'help' for its command line
126
+ interpreter.
127
+
128
+ Usage:
129
+ fluttrly -h/help
130
+ fluttrly <command> <list> <message for posting>
131
+
132
+ Examples:
133
+ fluttrly list bouverdafs Output the list "Bouverdafs"
134
+ fluttrly post bouverdafs "winning" Add to the list bouverdafs the message
135
+ "winning"
136
+ fluttrly update bouverdafs Presents the user with a prompt to
137
+ allow them to update a specific item
138
+ on that list.
139
+ fluttrly delete bouverdafs Just like `update`,except allows user
140
+ to delete a specific item from list.
141
+
142
+ For more information please go to:
143
+ http://github.com/brntbeer/fluttrly-gem
144
+
145
+ }.gsub(/^ {8}/, '') #to strip 8 lines of whitespace
146
+ puts text
147
+ end
148
+
149
+ private
150
+
151
+ # Private: Gathers the appropriate response based upon what kind
152
+ # of argument needs to be done.
153
+ #
154
+ # list - List to gather the response from.
155
+ # get - Optional flag to pass for if we're simply getting a
156
+ # refresh view of the list.
157
+ #
158
+ # Returns a Net::HTTP object for the given url, and a response.
159
+ def form_response(list, get=nil)
160
+
161
+ #refactors are welcome here =\
162
+ if get.nil?
163
+ uri = URI.parse("http://fluttrly.com/#{list}")
164
+ else
165
+ uri = URI.parse("http://fluttrly.com/#{list}.json")
166
+ end
167
+
168
+ http = Net::HTTP.new(uri.host, uri.port)
169
+ response = http.request(Net::HTTP::Get.new(uri.request_uri))
170
+ [http, response]
171
+ end
172
+
173
+
174
+ # Private: Used to set the actual post message.
175
+ #
176
+ # list - List to perform the post on.
177
+ # message - Message to post on the list.
178
+ # response - Response from a previous http request, used to
179
+ # get cookie and csrf token.
180
+ # http - Net::HTTP object used to post the actual data.
181
+ #
182
+ # Returns nothing.
183
+ def post_request(list, message, response, http)
184
+ auth_token = $1 if response.body =~ /"authenticity_token".*value="(.+)"/ or nil
185
+ raise "Not authenticated to perform this action." if auth_token.nil?
186
+
187
+ #COOKIE COOKIE COOKIE COOKIE COOKIE COOKIE
188
+ cookie = response['set-cookie'].split('; ')[0]
189
+
190
+ uri = URI.parse('http://fluttrly.com/tasks.js')
191
+ request = Net::HTTP::Post.new(uri.request_uri)
192
+ params = {
193
+ 'authenticity_token' => auth_token,
194
+ 'task[name]' => "#{list}",
195
+ 'task[content]' => "#{message}"
196
+ }
197
+ request["Cookie"] = cookie
198
+ request.set_form_data(params)
199
+ response = http.request(request)
200
+ end
201
+
202
+ # Private: Performs the PUT method to update a given task.
203
+ #
204
+ # id - The ID of the task we're updating.
205
+ # response - Response from a previous http request, used to
206
+ # get cookie and csrf token.
207
+ #
208
+ # Returns nothing.
209
+ def update_task(id, response)
210
+ auth_token = $1 if response.body =~ /"csrf-token".*content="(.+)"/ or nil
211
+ raise "Not authenticated to perform this action." if auth_token.nil?
212
+
213
+ #COOKIE COOKIE COOKIE COOKIE COOKIE COOKIE
214
+ cookie = response['set-cookie'].split('; ')[0]
215
+
216
+ uri = URI.parse("http://fluttrly.com/tasks/#{id}")
217
+ http = Net::HTTP.new(uri.host, uri.port)
218
+ request = Net::HTTP::Put.new(uri.request_uri)
219
+ params = {
220
+ 'authenticity_token' => auth_token,
221
+ 'completed' => "true"
222
+ }
223
+ request["Cookie"] = cookie
224
+ request.set_form_data(params)
225
+ response = http.request(request)
226
+ end
227
+
228
+ # Private: Performs the DELETE method to delete task(s)
229
+ #
230
+ # id - The ID or ids of the task(s) we're updating
231
+ # response - The response from a previous http request, used to
232
+ # get cookie and csrf token.
233
+ #
234
+ # Returns nothing.
235
+ def delete_task(id, response)
236
+ auth_token = $1 if response.body =~ /"csrf-token".*content="(.+)"/ or nil
237
+ raise "Not authenticated to perform this action." if auth_token.nil?
238
+
239
+ cookie = response['set-cookie'].split('; ')[0]
240
+
241
+ uri = URI.parse("http://fluttrly.com/tasks/#{id}")
242
+ http = Net::HTTP.new(uri.host, uri.port)
243
+ request = Net::HTTP::Delete.new(uri.request_uri)
244
+ params = {
245
+ 'authenticity_token' => auth_token,
246
+ }
247
+ request["Cookie"] = cookie
248
+ request.set_form_data(params)
249
+ response = http.request(request)
250
+ end
251
+ end
252
+ end
253
+ end
@@ -1,3 +1,3 @@
1
1
  module Fluttrly
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
@@ -0,0 +1,34 @@
1
+ require 'test/unit'
2
+ require 'rubygems'
3
+ require 'fluttrly-gem'
4
+ require 'net/http'
5
+ require 'JSON'
6
+
7
+ class TestCommand < Test::Unit::TestCase
8
+
9
+ def setup
10
+ @list = Fluttrly::Command.list("bouverdafs")
11
+ @finished = @list.select{|item| item["task"]["completed"] == true }
12
+ end
13
+
14
+ def test_list_size_increases_after_post
15
+ Fluttrly::Command.post("bouverdafs", "8=======D~~~~")
16
+ new_size = Fluttrly::Command.list("bouverdafs").size
17
+ assert (new_size > @list.size)
18
+ end
19
+
20
+ def test_list_update_includes_newly_completed_item
21
+ Fluttrly::Command.update("bouverdafs", 1)
22
+ list = Fluttrly::Command.list("bouverdafs")
23
+ finished = list.select{|item| item["task"]["completed"] == true}
24
+ assert list.include?(finished.first)
25
+ end
26
+
27
+ def test_size_decreases_after_delete
28
+ #offset the item to be deleted due to code looking at num-1
29
+ Fluttrly::Command.delete("bouverdafs", (@list.size-@finished.size)+1)
30
+ new_size = Fluttrly::Command.list("bouverdafs").size
31
+ assert (new_size < @list.size)
32
+ end
33
+
34
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluttrly
3
3
  version: !ruby/object:Gem::Version
4
- hash: 23
5
- prerelease: false
4
+ hash: 21
5
+ prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 4
10
- version: 0.0.4
9
+ - 5
10
+ version: 0.0.5
11
11
  platform: ruby
12
12
  authors:
13
13
  - Brent Beer
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-02-12 00:00:00 -06:00
18
+ date: 2011-05-17 00:00:00 -07:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -52,7 +52,9 @@ files:
52
52
  - bin/fluttrly
53
53
  - fluttrly-gem.gemspec
54
54
  - lib/fluttrly-gem.rb
55
+ - lib/fluttrly-gem/command.rb
55
56
  - lib/fluttrly-gem/version.rb
57
+ - test/test_command.rb
56
58
  has_rdoc: true
57
59
  homepage: http://rubygems.org/gems/fluttrly
58
60
  licenses: []
@@ -83,9 +85,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
83
85
  requirements: []
84
86
 
85
87
  rubyforge_project: fluttrly-gem
86
- rubygems_version: 1.3.7
88
+ rubygems_version: 1.6.0
87
89
  signing_key:
88
90
  specification_version: 3
89
91
  summary: Fluttrly.com command line interface.
90
- test_files: []
91
-
92
+ test_files:
93
+ - test/test_command.rb