smartfm 0.3.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 +38 -0
  2. data/README +45 -0
  3. data/Rakefile +155 -0
  4. data/examples/pure_ruby.rb +118 -0
  5. data/lib/ext/hash.rb +52 -0
  6. data/lib/smartfm.rb +16 -0
  7. data/lib/smartfm/core.rb +3 -0
  8. data/lib/smartfm/core/auth.rb +39 -0
  9. data/lib/smartfm/core/config.rb +51 -0
  10. data/lib/smartfm/core/version.rb +14 -0
  11. data/lib/smartfm/model.rb +5 -0
  12. data/lib/smartfm/model/base.rb +26 -0
  13. data/lib/smartfm/model/item.rb +174 -0
  14. data/lib/smartfm/model/list.rb +138 -0
  15. data/lib/smartfm/model/sentence.rb +118 -0
  16. data/lib/smartfm/model/user.rb +108 -0
  17. data/lib/smartfm/rest_client.rb +8 -0
  18. data/lib/smartfm/rest_client/base.rb +173 -0
  19. data/lib/smartfm/rest_client/item.rb +14 -0
  20. data/lib/smartfm/rest_client/list.rb +15 -0
  21. data/lib/smartfm/rest_client/sentence.rb +12 -0
  22. data/lib/smartfm/rest_client/user.rb +13 -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
data/ChangeLog ADDED
@@ -0,0 +1,38 @@
1
+ == 0.0.1 / 2008-10-13
2
+
3
+ * initial release
4
+
5
+ == 0.0.2
6
+
7
+ == 0.0.3
8
+
9
+ == 0.0.4
10
+
11
+ * add new API calls
12
+ * add new attributes
13
+
14
+ == 0.1.0
15
+
16
+ * add Smartfm::Auth (supports basic_auth and oauth)
17
+ * add List#create, List#delete, List#add_item, List#delete_item
18
+
19
+ == 0.1.1
20
+
21
+ * remove Mechanize
22
+
23
+ == 0.2.0
24
+
25
+ * support almost all API calls
26
+
27
+ == 0.2.1
28
+
29
+ * maintenance release
30
+
31
+ == 0.2.2
32
+
33
+ * add attribution support for add_image & add_sound APIs
34
+
35
+ == 0.3.0
36
+
37
+ * iKnow! => smart.fm
38
+ * now, iKnow! is the name of Flash study application
data/README ADDED
@@ -0,0 +1,45 @@
1
+ = smart.fm
2
+
3
+ by nov <nov@cerego.com>
4
+
5
+ == Description
6
+
7
+ This rubygem is a wrapper of smart.fm API.
8
+ You can get pure-ruby example at examples/pure_ruby.rb.
9
+ http://github.com/nov/smartfm/tree/master/examples/pure_ruby.rb
10
+
11
+ It shows all API calls you can use with this gem.
12
+
13
+ == Installation
14
+
15
+ git clone http://github.com/nov/smartfm.git
16
+ cd smartfm
17
+ rake install
18
+
19
+ === Archive Installation
20
+
21
+ rake install
22
+
23
+ === Gem Installation
24
+
25
+ gem install smartfm
26
+
27
+ == Features/Problems
28
+
29
+ Test! Test!! Test!!!
30
+
31
+ Create/Add/Delete APIs are not implemented.
32
+ They will be implemented in a few weeks.
33
+
34
+ smart.fm OAuth is still pre-alpha.
35
+
36
+ == Synopsis
37
+
38
+ See examples and smart.fm Developers, please.
39
+ smart.fm Developers (http://developer.smart.fm)
40
+
41
+ == Copyright
42
+
43
+ Author:: nov <nov@cerego.com>
44
+ Copyright:: Copyright (c) 2009 nov
45
+ License:: MIT License
data/Rakefile ADDED
@@ -0,0 +1,155 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/clean'
4
+ require 'rake/testtask'
5
+ require 'rake/packagetask'
6
+ require 'rake/gempackagetask'
7
+ require 'rake/rdoctask'
8
+ require 'rake/contrib/rubyforgepublisher'
9
+ require 'rake/contrib/sshpublisher'
10
+ require 'fileutils'
11
+ include FileUtils
12
+
13
+ NAME = "smartfm"
14
+ AUTHOR = "nov"
15
+ EMAIL = "developer@smart.fm"
16
+ DESCRIPTION = "A rubygem for smart.fm APIs"
17
+ RUBYFORGE_PROJECT = NAME
18
+ HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
19
+ BIN_FILES = %w( )
20
+
21
+ $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/lib"
22
+ require 'lib/smartfm'
23
+ VERS = Smartfm::Version.to_version
24
+ REV = File.read(".svn/entries")[/committed-rev="(d+)"/, 1] rescue nil
25
+ CLEAN.include ['**/.*.sw?', '*.gem', '.config']
26
+ RDOC_OPTS = [
27
+ '--title', "#{NAME} documentation",
28
+ "--charset", "utf-8",
29
+ "--opname", "index.html",
30
+ "--line-numbers",
31
+ "--main", "README",
32
+ "--inline-source",
33
+ ]
34
+
35
+ task :default => [:test]
36
+ task :package => [:clean]
37
+
38
+ Rake::TestTask.new("test") do |t|
39
+ t.libs << "test"
40
+ t.pattern = "test/**/*_test.rb"
41
+ t.verbose = true
42
+ end
43
+
44
+ Rake::TestTask.new("spec") do |t|
45
+ t.libs << "spec"
46
+ t.pattern = "spec/**/*_spec.rb"
47
+ t.verbose = true
48
+ end
49
+
50
+ spec = Gem::Specification.new do |s|
51
+ s.name = NAME
52
+ s.version = VERS
53
+ s.platform = Gem::Platform::RUBY
54
+ s.has_rdoc = true
55
+ s.extra_rdoc_files = ["README", "ChangeLog"]
56
+ s.rdoc_options += RDOC_OPTS + ['--exclude', '^(examples|extras)/']
57
+ s.summary = DESCRIPTION
58
+ s.description = DESCRIPTION
59
+ s.author = AUTHOR
60
+ s.email = EMAIL
61
+ s.homepage = HOMEPATH
62
+ s.executables = BIN_FILES
63
+ s.rubyforge_project = RUBYFORGE_PROJECT
64
+ s.bindir = "bin"
65
+ s.require_path = "lib"
66
+ #s.autorequire = ""
67
+ s.test_files = Dir["test/*_test.rb"]
68
+
69
+ s.add_dependency('json')
70
+ s.add_dependency('oauth')
71
+ # s.required_ruby_version = '>= 1.8.6'
72
+
73
+ s.files = %w(README ChangeLog Rakefile) +
74
+ Dir.glob("{bin,doc,test,spec,lib,templates,extras,website,script}/**/*") +
75
+ Dir.glob("ext/**/*.{h,c,rb}") +
76
+ Dir.glob("examples/**/*.rb") +
77
+ Dir.glob("tools/*.rb") +
78
+ Dir.glob("rails/*.rb")
79
+
80
+ s.extensions = FileList["ext/**/extconf.rb"].to_a
81
+ end
82
+
83
+ Rake::GemPackageTask.new(spec) do |p|
84
+ p.need_tar = true
85
+ p.gem_spec = spec
86
+ end
87
+
88
+ desc "Install"
89
+ task :install do
90
+ name = "#{NAME}-#{VERS}.gem"
91
+ sh %{rake package}
92
+ sh %{sudo gem install pkg/#{name}}
93
+ end
94
+
95
+ desc "Uninstall"
96
+ task :uninstall => [:clean] do
97
+ sh %{sudo gem uninstall #{NAME}}
98
+ end
99
+
100
+
101
+ Rake::RDocTask.new do |rdoc|
102
+ rdoc.rdoc_dir = 'html'
103
+ rdoc.options += RDOC_OPTS
104
+ rdoc.template = "resh"
105
+ #rdoc.template = "#{ENV['template']}.rb" if ENV['template']
106
+ if ENV['DOC_FILES']
107
+ rdoc.rdoc_files.include(ENV['DOC_FILES'].split(/,\s*/))
108
+ else
109
+ rdoc.rdoc_files.include('README', 'ChangeLog')
110
+ rdoc.rdoc_files.include('lib/**/*.rb')
111
+ rdoc.rdoc_files.include('ext/**/*.c')
112
+ end
113
+ end
114
+
115
+ desc "Publish to RubyForge"
116
+ task :rubyforge => [:rdoc, :package] do
117
+ require 'rubyforge'
118
+ Rake::RubyForgePublisher.new(RUBYFORGE_PROJECT, 'nov').upload
119
+ end
120
+
121
+ # rake release VERSION=x.y.z
122
+ desc 'Package and upload the release to rubyforge.'
123
+ task :release => [:clean, :package] do |t|
124
+ v = ENV["VERSION"] or abort "Must supply VERSION=x.y.z"
125
+ abort "Versions don't match #{v} vs #{VERS}" unless v == VERS
126
+ pkg = "pkg/#{NAME}-#{VERS}"
127
+
128
+ require 'rubyforge'
129
+ rf = RubyForge.new.configure
130
+ puts "Logging in"
131
+ rf.login
132
+
133
+ c = rf.userconfig
134
+ # c["release_notes"] = description if description
135
+ # c["release_changes"] = changes if changes
136
+ c["preformatted"] = true
137
+
138
+ files = [
139
+ "#{pkg}.tgz",
140
+ "#{pkg}.gem"
141
+ ].compact
142
+
143
+ puts "Releasing #{NAME} v. #{VERS}"
144
+ rf.add_release RUBYFORGE_PROJECT, NAME, VERS, *files
145
+ end
146
+
147
+ desc 'Show information about the gem.'
148
+ task :debug_gem do
149
+ puts spec.to_ruby
150
+ end
151
+
152
+ desc 'Update gem spec'
153
+ task :gemspec do
154
+ open("#{NAME}.gemspec", 'w').write spec.to_ruby
155
+ end
@@ -0,0 +1,118 @@
1
+ require 'rubygems'
2
+ require 'smartfm'
3
+ require 'oauth/consumer'
4
+
5
+ Smartfm::Config.init do |conf|
6
+ conf.api_host = 'api.smart.fm'
7
+ conf.api_key = '' # 'SET_YOUR_API_KEY'
8
+ conf.oauth_consumer_key = '' # 'SET_YOUR_OAUTH_CONSUMER_KEY'
9
+ conf.oauth_consumer_secret = '' # 'SET_YOUR_OAUTH_CONSUMER_SECRET'
10
+ conf.oauth_http_method = :post
11
+ conf.oauth_scheme = :header
12
+ conf.timeout = 15
13
+ end
14
+
15
+ # Edit here
16
+ OAUTH_ACCESS_TOKEN = ''
17
+ OAUTH_ACCESS_TOKEN_SECRET = ''
18
+
19
+ # Edit here
20
+ SMARTFM_USERNAME = ''
21
+ SMARTFM_PASSWORD = ''
22
+
23
+ please_get_api_key =<<EOS
24
+ This example needs your own smart.fm API key.
25
+ (for only Smartfm::Item.extract example)
26
+
27
+ You can get smart.fm API key at smart.fm Developers.
28
+ smart.fm Developers (http://developer.smart.fm/)
29
+
30
+ Thanks!
31
+ EOS
32
+
33
+ if Smartfm::Config.api_key == ''
34
+ raise ArgumentError.new(please_get_api_key)
35
+ end
36
+
37
+
38
+ ###########################
39
+ ## WITHOUT AUTHORIZATION ##
40
+ ###########################
41
+
42
+ puts "WITHOUT AUTHORIZATION"
43
+
44
+ ## User API
45
+ puts "# User API Calls"
46
+ @user = Smartfm::User.find('kirk')
47
+ @user.items(:include_sentences => true)
48
+ @user.lists
49
+ @user.friends
50
+ @user.study.results
51
+ @user.study.total_summary
52
+ @matched_users = Smartfm::User.matching('matake')
53
+
54
+ ## List API
55
+ puts "# List API Calls"
56
+ @recent_lists = Smartfm::List.recent
57
+ @list = Smartfm::List.find(31509, :include_sentences => true, :include_items => true)
58
+ @list.items
59
+ @list.sentences
60
+ @matched_lists = Smartfm::List.matching("イタリア語であいさつ")
61
+
62
+ ## Item API
63
+ puts "# Item API Calls"
64
+ @recent_items = Smartfm::Item.recent(:include_sentences => true)
65
+ @item = Smartfm::Item.find(437525)
66
+ @matched_items = Smartfm::Item.matching('record', :include_sentences => true)
67
+ @items = Smartfm::Item.extract("sometimes, often, electrical")
68
+ @items.first.sentences
69
+
70
+ ## Sentence API
71
+ puts "# Sentence API Calls"
72
+ @recent_sentences = Smartfm::Sentence.recent
73
+ @sentence = Smartfm::Sentence.find(312271)
74
+ @matched_sentences = Smartfm::Sentence.matching('record')
75
+
76
+
77
+ ########################
78
+ ## WITH AUTHORIZATION ##
79
+ ########################
80
+
81
+ auth = case
82
+ when !OAUTH_ACCESS_TOKEN.empty?
83
+ if Smartfm::Config.oauth_consumer_key.empty? or Smartfm::Config.oauth_consumer_secret.empty?
84
+ raise ArgumentError.new("oauth_consumer_key and oauth_consumer_secret are required")
85
+ end
86
+ Smartfm::Auth.new(:token => OAUTH_ACCESS_TOKEN, :secret => OAUTH_ACCESS_TOKEN_SECRET)
87
+ when SMARTFM_USERNAME != ''
88
+ Smartfm::Auth.new(:username => SMARTFM_USERNAME, :password => SMARTFM_PASSWORD)
89
+ else
90
+ nil
91
+ end
92
+ unless auth
93
+ puts "Skip calls which require authentication"
94
+ exit
95
+ else
96
+ puts "## WITH AUTHORIZATION :: #{auth.mode}"
97
+ end
98
+
99
+ ## List API
100
+ puts "# List API"
101
+ @list = Smartfm::List.create(auth, :title => 'smart.fm gem test', :description => 'A list for smart.fm gem test')
102
+ @list.add_item(auth, Smartfm::Item.find(437525))
103
+ @list.delete_item(auth, @list.items.first)
104
+ @list.delete(auth)
105
+
106
+ ## Item API
107
+ puts "# Item API"
108
+ @item = Smartfm::Item.create(auth, :cue => {:text => 'hello world! 2', :language => 'en', :part_of_speech => 'E'},
109
+ :response => {:text => 'ハローワールド!', :language => 'ja'})
110
+ @item.add_image(auth, 'http://farm4.static.flickr.com/3276/3102381796_a33c1ffdf1.jpg')
111
+ @item.add_sound(auth, 'http://matake.jp/download/hello_world.mp3')
112
+ @item.add_tags(auth, 'sample', 'programming')
113
+
114
+ ## Sentence API
115
+ puts "# Sentence API"
116
+ @sentence = Smartfm::Sentence.create(auth, :text => 'Hello World!', :item => Smartfm::Item.matching('hello world').first)
117
+ @sentence.add_image(auth, 'http://farm4.static.flickr.com/3276/3102381796_a33c1ffdf1.jpg')
118
+ @sentence.add_sound(auth, 'http://matake.jp/download/hello_world.mp3')
data/lib/ext/hash.rb ADDED
@@ -0,0 +1,52 @@
1
+ class Hash
2
+
3
+ def to_http_str
4
+ result = ''
5
+ return result if self.empty?
6
+ self.each do |key, val|
7
+ result << "#{key}=#{URI.encode(val.to_s)}&"
8
+ end
9
+ result.chop
10
+ end
11
+
12
+ def symbolize_keys!
13
+ self.each do |key, value|
14
+ unless self.delete(key.to_s).nil?
15
+ if value.is_a?(Hash)
16
+ value.symbolize_keys!
17
+ elsif value.is_a?(Array)
18
+ value.map!{ |v| v.symbolize_keys! if v.is_a?(Hash) }
19
+ end
20
+ self[key.to_sym] = value
21
+ end
22
+ end
23
+ self
24
+ end
25
+
26
+ def stringfy_keys!
27
+ self.each do |key, value|
28
+ unless self.delete(key.to_sym).nil?
29
+ if value.is_a?(Hash)
30
+ value.stringfy_keys!
31
+ elsif value.is_a?(Array)
32
+ value.map!{ |v| v.stringfy_keys! if v.is_a?(Hash) }
33
+ end
34
+ self[key.to_s] = value
35
+ end
36
+ end
37
+ self
38
+ end
39
+
40
+ def stringfy_values!
41
+ self.each do |key, value|
42
+ if value.is_a?(Hash)
43
+ value.stringfy_values!
44
+ elsif value.is_a?(Array)
45
+ value.map!{ |v| v.stringfy_values! if v.is_a?(Hash) }
46
+ end
47
+ self[key] = value.to_s
48
+ end
49
+ self
50
+ end
51
+
52
+ end
data/lib/smartfm.rb ADDED
@@ -0,0 +1,16 @@
1
+ module Smartfm
2
+ end
3
+
4
+ require 'date'
5
+ require 'net/https'
6
+ require 'uri'
7
+
8
+ require 'rubygems'
9
+ require 'json'
10
+
11
+ require 'ext/hash'
12
+ require 'smartfm/core'
13
+ require 'smartfm/rest_client'
14
+ require 'smartfm/model'
15
+
16
+ Smartfm::Config.init
@@ -0,0 +1,3 @@
1
+ require 'smartfm/core/version'
2
+ require 'smartfm/core/config'
3
+ require 'smartfm/core/auth'
@@ -0,0 +1,39 @@
1
+ require 'oauth/consumer'
2
+
3
+ class Smartfm::Auth
4
+ attr_accessor :mode, :auth_token
5
+
6
+ class Basic
7
+ attr_reader :username, :password
8
+
9
+ def initialize(username, password)
10
+ @username = username
11
+ @password = password
12
+ end
13
+ end
14
+
15
+ def initialize(options = {})
16
+ if options[:username] && options[:password]
17
+ @mode = :basic_auth
18
+ @auth_token = Basic.new(options[:username], options[:password])
19
+ elsif options[:token] && options[:secret]
20
+ @mode = :oauth
21
+ @auth_token = OAuth::AccessToken.new(Smartfm::Auth.consumer, options[:token], options[:secret])
22
+ else
23
+ raise ArgumentError.new('{:auth => "oauth_access_token", :secret => "oauth_access_token_secret"} or {:username "smartfm_username", :password => "smartfm_password"} is needed')
24
+ end
25
+ end
26
+
27
+ def self.consumer
28
+ @@consumer ||= OAuth::Consumer.new(
29
+ Smartfm::Config.oauth_consumer_key,
30
+ Smartfm::Config.oauth_consumer_secret,
31
+ :http_method => Smartfm::Config.oauth_http_method,
32
+ :scheme => Smartfm::Config.oauth_scheme,
33
+ :site => Smartfm::Config.api_base_url,
34
+ :authorize_url => "#{Smartfm::Config.base_url}/oauth/authorize"
35
+ )
36
+ end
37
+
38
+ alias_method :account, :auth_token
39
+ end