nov-smartfm 0.4.0

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.
Files changed (40) hide show
  1. data/ChangeLog +43 -0
  2. data/README +45 -0
  3. data/Rakefile +155 -0
  4. data/examples/pure_ruby.rb +119 -0
  5. data/lib/ext/hash.rb +52 -0
  6. data/lib/smartfm/core/auth.rb +39 -0
  7. data/lib/smartfm/core/config.rb +51 -0
  8. data/lib/smartfm/core/version.rb +14 -0
  9. data/lib/smartfm/core.rb +3 -0
  10. data/lib/smartfm/model/base.rb +26 -0
  11. data/lib/smartfm/model/item.rb +178 -0
  12. data/lib/smartfm/model/list.rb +138 -0
  13. data/lib/smartfm/model/sentence.rb +118 -0
  14. data/lib/smartfm/model/user.rb +112 -0
  15. data/lib/smartfm/model.rb +5 -0
  16. data/lib/smartfm/rest_client/base.rb +194 -0
  17. data/lib/smartfm/rest_client/item.rb +14 -0
  18. data/lib/smartfm/rest_client/list.rb +15 -0
  19. data/lib/smartfm/rest_client/sentence.rb +12 -0
  20. data/lib/smartfm/rest_client/user.rb +14 -0
  21. data/lib/smartfm/rest_client.rb +8 -0
  22. data/lib/smartfm.rb +16 -0
  23. data/spec/ext/hash_spec.rb +11 -0
  24. data/spec/smartfm/core/auth_spec.rb +39 -0
  25. data/spec/smartfm/core/config_spec.rb +34 -0
  26. data/spec/smartfm/core/version_spec.rb +19 -0
  27. data/spec/smartfm/model/base_spec.rb +40 -0
  28. data/spec/smartfm/model/item_spec.rb +41 -0
  29. data/spec/smartfm/model/list_spec.rb +7 -0
  30. data/spec/smartfm/model/sentence_spec.rb +7 -0
  31. data/spec/smartfm/model/user_spec.rb +90 -0
  32. data/spec/smartfm/rest_client/base_spec.rb +9 -0
  33. data/spec/smartfm/rest_client/item_spec.rb +7 -0
  34. data/spec/smartfm/rest_client/list_spec.rb +7 -0
  35. data/spec/smartfm/rest_client/sentence_spec.rb +7 -0
  36. data/spec/smartfm/rest_client/user_spec.rb +7 -0
  37. data/spec/spec_helper.rb +18 -0
  38. data/test/smartfm_test.rb +8 -0
  39. data/test/test_helper.rb +3 -0
  40. metadata +132 -0
@@ -0,0 +1,178 @@
1
+ class Smartfm::Item < Smartfm::Base
2
+ ATTRIBUTES = [:sentences, :responses, :cue, :id, :list]
3
+ READONLY_ATTRIBUTES = [:sentences, :responses, :cue, :id]
4
+ attr_accessor *(ATTRIBUTES - READONLY_ATTRIBUTES)
5
+ attr_reader *READONLY_ATTRIBUTES
6
+
7
+ class Response < Smartfm::Base
8
+ ATTRIBUTES = [:text, :text_with_character, :type, :language]
9
+ READONLY_ATTRIBUTES = [:type]
10
+ attr_accessor *(ATTRIBUTES - READONLY_ATTRIBUTES)
11
+ attr_reader *READONLY_ATTRIBUTES
12
+
13
+ def initialize(params = {})
14
+ @text = params[:text]
15
+ @type = params[:type]
16
+ @language = params[:language]
17
+ end
18
+ end
19
+
20
+ class Cue < Smartfm::Base
21
+ ATTRIBUTES = [:type, :text, :image, :sound, :part_of_speech, :language, :transliterations]
22
+ READONLY_ATTRIBUTES = [:sound]
23
+ attr_accessor *(ATTRIBUTES - READONLY_ATTRIBUTES)
24
+ attr_reader *READONLY_ATTRIBUTES
25
+
26
+ def initialize(params = {})
27
+ @type = params[:type]
28
+ @text = params[:text]
29
+ @image = params[:image]
30
+ @sound = params[:sound]
31
+ @part_of_speech = params[:part_of_speech]
32
+ @language = params[:language]
33
+ @transliterations = params[:transliterations]
34
+ end
35
+ end
36
+
37
+ def self.recent(params = {})
38
+ hash = Smartfm::RestClient::Item.recent(params)
39
+ self.deserialize(hash) || []
40
+ end
41
+
42
+ def self.find(item_id, params = {})
43
+ params[:id] = item_id
44
+ hash = Smartfm::RestClient::Item.find(params)
45
+ self.deserialize(hash)
46
+ end
47
+
48
+ def self.matching(keyword, params = {})
49
+ params[:keyword] = keyword
50
+ hash = Smartfm::RestClient::Item.matching(params)
51
+ self.deserialize(hash) || []
52
+ end
53
+
54
+ def self.extract(text, params = {})
55
+ params[:text] = text
56
+ hash = Smartfm::RestClient::Item.extract(params)
57
+ if params[:words_only] == false
58
+ self.deserialize(hash) || []
59
+ else
60
+ hash
61
+ end
62
+ end
63
+
64
+ def self.create(auth, params = {})
65
+ self.new(params).save(auth)
66
+ end
67
+
68
+ def initialize(params = {})
69
+ params[:responses] = [params[:response]] if params[:response]
70
+ @id = params[:id].to_i
71
+ @list = params[:list]
72
+ @cue = self.deserialize(params[:cue], :as => Smartfm::Item::Cue)
73
+ @responses = self.deserialize(params[:responses], :as => Smartfm::Item::Response)
74
+ @sentences = self.deserialize(params[:sentences], :as => Smartfm::Sentence)
75
+ end
76
+
77
+ def save(auth)
78
+ begin
79
+ item_id = Smartfm::RestClient::Item.create(auth, self.to_post_data)
80
+ rescue
81
+ return false
82
+ end
83
+ Smartfm::Item.find(item_id)
84
+ end
85
+
86
+ def add_image(auth, params)
87
+ post_params = if params.is_a?(String)
88
+ { 'image[url]' => params }
89
+ else
90
+ image_params = {
91
+ 'image[url]' => params[:url],
92
+ 'image[list_id]' => params[:list_id]
93
+ }
94
+ if params[:attribution]
95
+ attribution_params = {
96
+ 'attribution[media_entity]' => params[:attribution][:media_entity],
97
+ 'attribution[author]' => params[:attribution][:media_entity],
98
+ 'attribution[author_url]' => params[:attribution][:media_entity],
99
+ 'attribution[attribution_license_id]' => params[:attribution][:media_entity]
100
+ }
101
+ image_params.merge(attribution_params)
102
+ else
103
+ image_params
104
+ end
105
+ end
106
+ Smartfm::RestClient::Item.add_image(auth, post_params.merge(:id => self.id))
107
+ end
108
+
109
+ def add_sound(auth, params)
110
+ post_params = if params.is_a?(String)
111
+ { 'sound[url]' => params }
112
+ else
113
+ sound_params = {
114
+ 'sound[url]' => params[:url],
115
+ 'sound[list_id]' => params[:list_id]
116
+ }
117
+ if params[:attribution]
118
+ attribution_params = {
119
+ 'attribution[media_entity]' => params[:attribution][:media_entity],
120
+ 'attribution[author]' => params[:attribution][:media_entity],
121
+ 'attribution[author_url]' => params[:attribution][:media_entity],
122
+ 'attribution[attribution_license_id]' => params[:attribution][:media_entity]
123
+ }
124
+ sound_params.merge(attribution_params)
125
+ else
126
+ sound_params
127
+ end
128
+ end
129
+ Smartfm::RestClient::Item.add_sound(auth, post_params.merge(:id => self.id))
130
+ end
131
+
132
+ def add_tags(auth, *tags)
133
+ post_params = {}
134
+ tags.each_with_index do |tag, idx|
135
+ if tag.is_a?(String)
136
+ post_params["semantic_tags[#{idx}][name]"] = tag
137
+ else
138
+ post_params["semantic_tags[#{idx}][name]"] = tag[:name]
139
+ post_params["semantic_tags[#{idx}][disambiguation]"] = tag[:disambiguation]
140
+ end
141
+ end
142
+ Smartfm::RestClient::Item.add_tags(auth, post_params.merge(:id => self.id))
143
+ end
144
+
145
+ protected
146
+
147
+ def to_post_data
148
+ self.validate
149
+ post_data = {
150
+ 'cue[text]' => self.cue.text,
151
+ 'cue[language]' => self.cue.language,
152
+ 'cue[part_of_speech]' => self.cue.part_of_speech,
153
+ 'response[text]' => self.response.text,
154
+ 'response[language]' => self.response.language
155
+ }
156
+ # Optional attributes
157
+ if self.list
158
+ post_data['item[list_id]'] = self.list.id
159
+ end
160
+ if response.text_with_character
161
+ post_data['character_response[text]'] = self.response.character_text
162
+ end
163
+ post_data
164
+ end
165
+
166
+ def validate
167
+ raise ArgumentError.new("Item cue[text] is required.") if self.cue.text.nil? or self.cue.text.empty?
168
+ raise ArgumentError.new("Item cue[language] is required.") if self.cue.language.nil? or self.cue.language.empty?
169
+ raise ArgumentError.new("Item cue[part_of_speech] is required.") if self.cue.part_of_speech.nil? or self.cue.part_of_speech.empty?
170
+ raise ArgumentError.new("Item response[text] is required.") if self.response.text.nil? or self.response.text.empty?
171
+ raise ArgumentError.new("Item response[language] is required.") if self.response.language.nil? or self.response.language.empty?
172
+ end
173
+
174
+ def response
175
+ self.responses.first
176
+ end
177
+
178
+ end
@@ -0,0 +1,138 @@
1
+ class Smartfm::List < Smartfm::Base
2
+ ATTRIBUTES = [:id, :title, :description, :icon, :square_icon, :item_count, :user_count, :iknow, :dictation, :brainspeed,
3
+ :language, :translation_language, :list_type, :transcript, :embed,
4
+ :tags, :media_entry, :author, :author_id, :author_url, :attribution_license_id,
5
+ :items, :sentences]
6
+ READONLY_ATTRIBUTES = [:id, :icon, :item_count, :user_count, :iknow, :dictation, :brainspeed]
7
+ attr_accessor *(ATTRIBUTES - READONLY_ATTRIBUTES)
8
+ attr_reader *READONLY_ATTRIBUTES
9
+
10
+ class Application < Smartfm::Base
11
+ ATTRIBUTES = [:application, :list_id, :lang]
12
+ attr_reader *ATTRIBUTES
13
+
14
+ def initialize(params = {})
15
+ @application = params[:application]
16
+ @list_id = params[:list_id]
17
+ @lang = params[:lang]
18
+ end
19
+ def url
20
+ "http://smart.fm/flash?swf=#{self.name}&course_id=#{self.list_id}&lang=#{self.lang}"
21
+ end
22
+ end
23
+
24
+ def self.recent(params = {})
25
+ hash = Smartfm::RestClient::List.recent(params)
26
+ self.deserialize(hash) || []
27
+ end
28
+
29
+ def self.find(list_id, params = {})
30
+ params[:id] = list_id
31
+ hash = Smartfm::RestClient::List.find(params)
32
+ self.deserialize(hash)
33
+ end
34
+
35
+ def self.matching(keyword, params = {})
36
+ params[:keyword] = keyword
37
+ hash = Smartfm::RestClient::List.matching(params)
38
+ self.deserialize(hash) || []
39
+ end
40
+
41
+ def self.create(auth, params = {})
42
+ self.new(params).save(auth)
43
+ end
44
+
45
+ def self.delete(list_id)
46
+ self.find(list_id).delete
47
+ end
48
+
49
+ def initialize(params = {})
50
+ @id = (params[:id].to_i rescue nil)
51
+ @title = params[:title]
52
+ @description = params[:description]
53
+ @icon = params[:icon]
54
+ @square_icon = params[:square_icon]
55
+ @item_count = (params[:item_count].to_i rescue nil)
56
+ @user_count = (params[:user_count].to_i rescue nil)
57
+ @language = params[:language]
58
+ @translation_language = params[:translation_language]
59
+ if @list_id and @translation_language
60
+ common_settings = {:list_id => @id, :lang => @translation_language}
61
+ @iknow = Application.new(common_settings.merge(:application => 'iknow')) if params[:iknow]
62
+ @dictation = Application.new(common_settings.merge(:application => 'dictation')) if params[:dictation]
63
+ @brainspeed = Application.new(common_settings.merge(:application => 'brainspeed')) if params[:brainspeed]
64
+ end
65
+ @author = params[:author] # display_name or username
66
+ @author_id = params[:author_id] # username
67
+ @author_url = params[:author_url]
68
+ @list_type = params[:list_type] # for list creation
69
+ @transcript = params[:transcript] # for list creation
70
+ @embed = params[:embed] # for list creation
71
+ @tags = params[:tags] # for list creation
72
+ @media_entry = params[:media_entry] # for list creation
73
+ @attribution_license_id = params[:attribution_license_id] # for list creation
74
+ @items = self.deserialize(params[:items], :as => Smartfm::Item)
75
+ @sentences = self.deserialize(params[:sentences], :as => Smartfm::Sentence)
76
+ end
77
+
78
+ def items(params = {})
79
+ hash = Smartfm::RestClient::List.items(params.merge(:id => self.id))
80
+ self.deserialize(hash, :as => Smartfm::Item) || []
81
+ end
82
+
83
+ def sentences(params = {})
84
+ hash = Smartfm::RestClient::List.sentences(params.merge(:id => self.id))
85
+ self.deserialize(hash, :as => Smartfm::Sentence) || []
86
+ end
87
+
88
+ def save(auth)
89
+ begin
90
+ list_id = Smartfm::RestClient::List.create(auth, self.to_post_data)
91
+ rescue
92
+ return false
93
+ end
94
+ Smartfm::List.find(list_id)
95
+ end
96
+
97
+ def delete(auth)
98
+ Smartfm::RestClient::List.delete(auth, {:id => self.id})
99
+ end
100
+ alias_method :destroy, :delete
101
+
102
+ def add_item(auth, item)
103
+ Smartfm::RestClient::List.add_item(auth, {:list_id => self.id, :id => item.id})
104
+ end
105
+
106
+ def delete_item(auth, item)
107
+ Smartfm::RestClient::List.delete_item(auth, {:list_id => self.id, :id => item.id})
108
+ end
109
+
110
+ protected
111
+
112
+ def to_post_data
113
+ self.validate
114
+ post_data = {
115
+ 'list[name]' => self.title,
116
+ 'list[description]' => self.description,
117
+ 'list[language]' => self.language || 'en',
118
+ 'list[translation_language]' => self.translation_language || 'ja'
119
+ }
120
+ # Optional attributes
121
+ if self.list_type
122
+ post_data['list[type]'] = self.list_type
123
+ end
124
+ [ :transcript, :embed, :tags, :media_entry,
125
+ :author, :author_url, :attribution_license_id ].each do |key|
126
+ if self.send("#{key}")
127
+ post_data["list[#{key}]"] = self.send("#{key}")
128
+ end
129
+ end
130
+ post_data
131
+ end
132
+
133
+ def validate
134
+ raise ArgumentError.new("List title is required.") if self.title.nil? or self.title.empty?
135
+ raise ArgumentError.new("List description is required.") if self.description.nil? or self.description.empty?
136
+ end
137
+
138
+ end
@@ -0,0 +1,118 @@
1
+ class Smartfm::Sentence < Smartfm::Base
2
+ ATTRIBUTES = [:sound, :image, :square_image, :text, :language, :id, :transliterations, :translations, :item, :list]
3
+ READONLY_ATTRIBUTES = [:id]
4
+ attr_accessor *(ATTRIBUTES - READONLY_ATTRIBUTES)
5
+ attr_reader *READONLY_ATTRIBUTES
6
+
7
+ def self.recent(params = {})
8
+ hash = Smartfm::RestClient::Sentence.recent(params)
9
+ self.deserialize(hash) || []
10
+ end
11
+
12
+ def self.find(sentence_id, params = {})
13
+ params[:id] = sentence_id
14
+ hash = Smartfm::RestClient::Sentence.find(params)
15
+ self.deserialize(hash)
16
+ end
17
+
18
+ def self.matching(keyword, params = {})
19
+ params[:keyword] = keyword
20
+ hash = Smartfm::RestClient::Sentence.matching(params)
21
+ self.deserialize(hash) || []
22
+ end
23
+
24
+ def self.create(auth, params = {})
25
+ self.new(params).save(auth)
26
+ end
27
+
28
+ def initialize(params = {})
29
+ params[:translations] = [params[:translation]] if params[:translation]
30
+ params[:transliterations] = [params[:transliteration]] if params[:transliteration]
31
+ @id = params[:id]
32
+ @item = params[:item]
33
+ @list = params[:list]
34
+ @sound = params[:sound]
35
+ @image = params[:image]
36
+ @square_image = params[:square_image]
37
+ @text = params[:text]
38
+ @language = params[:language]
39
+ @transliterations = params[:transliterations]
40
+ @translations = self.deserialize(params[:translations], :as => Smartfm::Sentence)
41
+ end
42
+
43
+ def save(auth)
44
+ begin
45
+ sentence_id = Smartfm::RestClient::Sentence.create(auth, self.to_post_data)
46
+ rescue
47
+ return false
48
+ end
49
+ Smartfm::Sentence.find(sentence_id)
50
+ end
51
+
52
+ def add_image(auth, params)
53
+ post_params = if params.is_a?(String)
54
+ {'image[url]' => params}
55
+ else
56
+ {'image[url]' => params[:url], 'image[list_id]' => params[:list_id]}.merge(attribution_params(params[:attribution]))
57
+ end
58
+ Smartfm::RestClient::Sentence.add_image(auth, post_params.merge(:id => self.id))
59
+ end
60
+
61
+ def add_sound(auth, params)
62
+ post_params = if params.is_a?(String)
63
+ {'sound[url]' => params}
64
+ else
65
+ {'sound[url]' => params[:url], 'sound[list_id]' => params[:list_id]}.merge(attribution_params(params[:attribution]))
66
+ end
67
+ Smartfm::RestClient::Sentence.add_sound(auth, post_params.merge(:id => self.id))
68
+ end
69
+
70
+ protected
71
+
72
+ def to_post_data
73
+ self.validate
74
+ post_data = {
75
+ 'item_id' => self.item.id,
76
+ 'sentence[text]' => self.text
77
+ }
78
+ # Optional attributes
79
+ if self.list
80
+ post_data['sentence[list_id]'] = self.list.id
81
+ end
82
+ [:language, :transliteration].each do |key|
83
+ if self.send("#{key}")
84
+ post_data["sentence[#{key}]"] = self.send("#{key}")
85
+ end
86
+ end
87
+ if self.translation
88
+ [:text, :language, :transliteration].each do |key|
89
+ if self.translation.send("#{key}")
90
+ post_data["translation[#{key}]"] = self.translation.send("#{key}")
91
+ end
92
+ end
93
+ end
94
+ post_data
95
+ end
96
+
97
+ def validate
98
+ raise ArgumentError.new("Item is required.") unless self.item
99
+ raise ArgumentError.new("Sentence text is required.") if self.text.nil? or self.text.empty?
100
+ end
101
+
102
+ def translation
103
+ self.translations.first rescue nil
104
+ end
105
+
106
+ def transliteration
107
+ self.transliterations.first rescue nil
108
+ end
109
+
110
+ def attribution_params(attr_params)
111
+ return {} unless attr_params
112
+ {'attribution[medias_entity]' => attr_params[:media_entity],
113
+ 'attribution[author]' => attr_params[:author],
114
+ 'attribution[author_url]' => attr_params[:author_url],
115
+ 'attributions[attribution_license_id]' => attr_params[:attribution_license_id] }
116
+ end
117
+
118
+ end
@@ -0,0 +1,112 @@
1
+ class Smartfm::User < Smartfm::Base
2
+ ATTRIBUTES = [:username, :profile]
3
+ attr_reader *ATTRIBUTES
4
+
5
+ class Profile < Smartfm::Base
6
+ ATTRIBUTES = [:name, :gender, :birthday, :description, :blog_url, :profile_url, :foaf_url, :icon_url]
7
+ attr_reader *ATTRIBUTES
8
+
9
+ def initialize(params = {})
10
+ @name = params[:name]
11
+ @gender = params[:gender]
12
+ @birthday = (Date.parse(params[:birthday]) rescue nil)
13
+ @description = params[:description]
14
+ @blog_url = params[:blog_url]
15
+ @profile_url = params[:profile_url]
16
+ @foaf_url = params[:foaf_url]
17
+ @icon_url = params[:icon_url]
18
+ end
19
+ end
20
+
21
+ class Study < Smartfm::Base
22
+ ATTRIBUTES = [:today, :results, :total_summary]
23
+ attr_reader *ATTRIBUTES
24
+
25
+ class Result < Smartfm::Base
26
+ ATTRIBUTES = [:timestamp, :seconds, :totals, :seen, :completed, :date]
27
+ attr_reader *ATTRIBUTES
28
+
29
+ def initialize(params = {})
30
+ @timestamp = (params[:timestamp].to_i rescue nil)
31
+ @seconds = (params[:seconds].to_i rescue nil)
32
+ @totals = {
33
+ :seconds => (params[:totals][:seconds].to_i rescue nil),
34
+ :seen => (params[:totals][:seen].to_i rescue nil),
35
+ :completed => (params[:totals][:completed].to_i rescue nil)
36
+ }
37
+ @seen = (params[:seen].to_i rescue nil)
38
+ @completed = (params[:completed].to_i rescue nil)
39
+ @date = (Date.parse(params[:date]) rescue nil)
40
+ end
41
+ end
42
+
43
+ class TotalSummary < Smartfm::Base
44
+ ATTRIBUTES = [:studied, :completed, :performance, :best_speed, :best_score]
45
+ attr_reader *ATTRIBUTES
46
+
47
+ def initialize(params = {})
48
+ @studied = params[:studied]
49
+ @completed = params[:completed]
50
+ @performance = params[:performance]
51
+ @best_speed = params[:best_speed]
52
+ @best_score = params[:best_score]
53
+ end
54
+ end
55
+
56
+ def initialize(params = {})
57
+ @today = (Date.parse(params[:today]) rescue nil)
58
+ @results = self.deserialize(params[:study_results], :as => Smartfm::User::Study::Result)
59
+ @total_summary = self.deserialize(params[:total_summary], :as => Smartfm::User::Study::TotalSummary)
60
+ end
61
+
62
+ end
63
+
64
+ def self.find(username, params = {})
65
+ params[:username] = username
66
+ hash = Smartfm::RestClient::User.find(params)
67
+ self.deserialize(hash)
68
+ end
69
+
70
+ def self.matching(keyword, params = {})
71
+ params[:keyword] = keyword
72
+ hash = Smartfm::RestClient::User.matching(params)
73
+ self.deserialize(hash) || []
74
+ end
75
+
76
+ def self.username(auth)
77
+ Smartfm::RestClient::User.username(auth, {})
78
+ end
79
+
80
+ def initialize(params)
81
+ @profile = Profile.new(params[:profile])
82
+ @username = params[:username]
83
+ end
84
+
85
+ def items(params = {})
86
+ hash = Smartfm::RestClient::User.items(params.merge(:username => self.username))
87
+ self.deserialize(hash, :as => Smartfm::Item) || []
88
+ end
89
+
90
+ def lists(params = {})
91
+ hash = Smartfm::RestClient::User.lists(params.merge(:username => self.username))
92
+ self.deserialize(hash, :as => Smartfm::List) || []
93
+ end
94
+
95
+ def friends(params = {})
96
+ hash = Smartfm::RestClient::User.friends(params.merge(:username => self.username))
97
+ self.deserialize(hash) || []
98
+ end
99
+
100
+ def followers(params = {})
101
+ hash = Smartfm::RestClient::User.followers(params.merge(:username => self.username))
102
+ self.deserialize(hash) || []
103
+ end
104
+
105
+ def study(params = {})
106
+ params[:application] ||= 'iknow'
107
+ return nil unless ['iknow', 'dictation', 'brainspeed', ].include?(params[:application])
108
+ hash = Smartfm::RestClient::User.study_results(params.merge(:username => self.username))
109
+ self.deserialize(hash, :as => Smartfm::User::Study)
110
+ end
111
+
112
+ end
@@ -0,0 +1,5 @@
1
+ require 'smartfm/model/base'
2
+ require 'smartfm/model/user'
3
+ require 'smartfm/model/list'
4
+ require 'smartfm/model/item'
5
+ require 'smartfm/model/sentence'