duwanis-rubyku 0.0.3 → 0.1.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.
data/README CHANGED
@@ -8,33 +8,39 @@ Rubyku is a ruby library for accessing data via the Jaiku API.
8
8
 
9
9
  == FEATURES/PROBLEMS:
10
10
 
11
- Authorization against Jaiku is done using the Rubyku::Credentials object.
12
- While the Jaiku API uses an API key instead of the username/password, I
13
- thought it would be nice to allow for both.
14
- So the api_key property on credentials will lazy-load itself (by logging
15
- into the site and fetching it for you) if you populate the Credentials
16
- object with a proper username and password.
17
- Example:
18
- cred = Rubyku::Credentials.new
19
- cred.username = 'duwanis'
20
- cred.password = 'notmyrealpassword'
21
- cred.api_key
22
- > "1n2o3t4m5y6a7p8i9k0e1y"
23
-
24
- Everything you may need to configure should be accessible via the
25
- Rubyku::Settings object. So far:
26
- proxy_url
27
- proxy_port
28
- jaiku_credentials #this is a place to save a default login, for a single-user app
29
- logger #an instance of Logger that will be used by rubyku for, well, logging.
30
-
31
- == SYNOPSIS:
32
-
33
- No synopsis yet, but I'm working on it
11
+ Rubyku 0.1.0: Bringing home the [user]bacon
12
+
13
+ Users are now fully functional (woo!). Messages still need some work
14
+ done to them, and then after that we still need to work on being able
15
+ to post. But you should be able to read anything you've ever wanted to
16
+ read from a user now.
17
+
18
+ == EXAMPLE:
19
+
20
+ Just to whet your appetite:
21
+
22
+ #provide log in details for the service
23
+ cred = Rubyku::Credentials.new
24
+ cred.username = 'duwanis'
25
+ cred.password = 'password' # or cred.api_key = 'apikeygoeshere' if you want to do it that way
26
+ Rubyku::Settings.jaiku_credentials = cred #so you don't have to keep passing cred around
27
+ user = Rubyku::User.fetch 'duwanis' #and now we're off to the races
28
+ user.updates # => a list of Rubyku::Messages representing my latest updates
29
+ user.stream # => a list of Rubyku::Messages representing my contacts' latest updates
30
+
31
+ etc. Have fun :)
34
32
 
35
33
  == REQUIREMENTS:
36
34
 
37
- none atm
35
+ Currently, the only other gem required for rubyku is json > 1.0.0.
36
+ I'm trying to keep it simple.
37
+
38
+ == TESTING:
39
+
40
+ Hah, notice how there isn't any automated testing?
41
+ I'd really like to have automated test suites for rubyku, but it's
42
+ not an easy thing to do since it's so tightly coupled with a web
43
+ service that requires authentication. Let me know if you have any ideas, though.
38
44
 
39
45
  == INSTALL:
40
46
 
@@ -1,4 +1,26 @@
1
1
  module Rubyku
2
+ ##
3
+ # This class represents the credentials necessary to log in
4
+ # to the Jaiku service in order to access non-public portions
5
+ # of the API.
6
+ # It has 3 fields:
7
+ # - +username+
8
+ # - +password+
9
+ # - +api_key+
10
+ # Only +username+ and +api_key+ are required to log in to Jaiku.
11
+ # Password is offered as a way to make things easier for the user:
12
+ # since API keys aren't easily memorable (and subject to change, in
13
+ # Jaiku's case), rubyku allows for setting the username and password
14
+ # alone. It will then fetch the api_key for the user.
15
+ # Example:
16
+ # cred = Rubyku::Credentials.new
17
+ # cred.username = 'duwanis'
18
+ # cred.password = 'notmyrealpassword'
19
+ # cred.api_key
20
+ # => 'apikey1234567890'
21
+ #
22
+ # For a single-user app, one instance of Rubyku::Credentials should
23
+ # be created and saved on the Rubyku::Settings class.
2
24
  class Credentials
3
25
  attr_accessor :username
4
26
  attr_accessor :password
@@ -6,18 +28,12 @@ module Rubyku
6
28
 
7
29
  ##
8
30
  # returns the Jaiku API key for these credentials.
9
- # This is a lazy-load property. Since there is a method
10
- # that can be used to retrieve the API key with the username
11
- # and password, rubyku does not require you to specify that
12
- # key if you would rather specify a username and password.
31
+ # This is a lazy-load property. Since there is a method
32
+ # that can be used to retrieve the API key with the username
33
+ # and password, rubyku does not require you to specify that
34
+ # key if you would rather specify a username and password.
13
35
  #
14
- # @return <String> the API key for this user.
15
- #
16
- # @raise <Rubyku::InvalidCredentialsError> indicates that the provided
17
- # username and password are not valid for Jaiku.
18
- #
19
- # @raise <RubykuError> indicates that there was an error communicating
20
- # to the Jaiku servers.
36
+ # returns: +String+ the API key for this user.
21
37
  #
22
38
  def api_key
23
39
  log = Rubyku::Settings.logger
@@ -43,24 +59,19 @@ module Rubyku
43
59
 
44
60
  ##
45
61
  # Given a username and password, retrieve that user's API key.
46
- # this works by logging the user in, stripping cookie information
47
- # off of the response, and then using that cookie information
48
- # to hit http://api.jaiku.com/key . All credit for this approach
49
- # to this python snippet on DZone: http://snippets.dzone.com/posts/show/5539
50
- # For the record, I'm torn about leaving this in. On the one hand it assumes
51
- # a lot about the internals of jaiku - on the other, it allows the user
52
- # to be oblivious to the API key and any changes it may undergo.
53
- #
54
- # @param username<String> the username to use for authentication.
55
- #
56
- # @param password<String> the password to use for authentication.
62
+ # this works by logging the user in, stripping cookie information
63
+ # off of the response, and then using that cookie information
64
+ # to hit http://api.jaiku.com/key . All credit for this approach
65
+ # to this python snippet on DZone: http://snippets.dzone.com/posts/show/5539
66
+ # For the record, I'm torn about leaving this in. On the one hand it assumes
67
+ # a lot about the internals of jaiku - on the other, it allows the user
68
+ # to be oblivious to the API key and any changes it may undergo.
57
69
  #
58
- # @raise <Rubyku::InvalidCredentialsError> indicates that the provided
59
- # username and password are not valid for Jaiku.
70
+ # returns: +String+ the API key for the user, if found.
60
71
  #
61
- # @raise <RubykuError> indicates that there was an error communicating
62
- # to the Jaiku servers.
63
- #
72
+ # raises:
73
+ # - Rubyku::InvalidCredentialsError - username/password were not valid.
74
+ # - Rubyku::Error - there was an error communicating with the Jaiku servers.
64
75
  def fetch_api_key(username, password)
65
76
  log = Rubyku::Settings.logger
66
77
 
@@ -80,7 +91,7 @@ module Rubyku
80
91
  #If Jaiku returns anything other than a redirect (which is expected
81
92
  # for a successful logon), then something's broke.
82
93
  log.error "Jaiku returned something other than a 303. Something borked."
83
- raise RubykuError, "Could not connect to http://www.jaiku.com/login to retrieve API key."
94
+ raise Rubyku::Error, "Could not connect to http://www.jaiku.com/login to retrieve API key."
84
95
  end
85
96
 
86
97
  #retrieve the cookie contents from the successful login result
data/lib/rubyku/errors.rb CHANGED
@@ -3,9 +3,12 @@ module Rubyku
3
3
  class Error < RuntimeError
4
4
  end
5
5
 
6
+ # Rubyku exception thrown when a specified user is not found.
6
7
  class UserNotFoundError < Error
7
8
  end
8
9
 
10
+ # Rubyku exception thrown when provided credentials are not
11
+ # correct.
9
12
  class InvalidCredentialsError < Error
10
13
  end
11
14
  end
@@ -0,0 +1,73 @@
1
+ module Rubyku
2
+
3
+ ##
4
+ # This class represents messages within Jaiku. The exact
5
+ # representation of the data will be different, depending on
6
+ # whether or not this message was in response to another message.
7
+ # The properties for a Message object are:
8
+ # - +id+: The unique id Jaiku has assigned to this message.
9
+ # - +title+: The text of the message, or the title of the message if
10
+ # this message is a response.
11
+ # - +entry_title+: The title of the original message (only present for comments)
12
+ # - +content+: The content of this message (only present for comments)
13
+ # - +pretty_content+: The content of this message + HTML formatting (only present for comments)
14
+ # - +url+: The url for this message.
15
+ # - +created_at+: An exact timestamp for this message's creation time.
16
+ # - +created_at_relative+: A friendly relative timestamp (e.g. '14 minutes ago')
17
+ # - +user+: An instance of +Rubyku::User+ representing the user who posted the message.
18
+ # - +comment+: A boolean property representing whether this message is a comment on another message.
19
+ class Message
20
+ attr_accessor :id
21
+ attr_accessor :title
22
+ attr_accessor :entry_title
23
+ attr_accessor :content
24
+ attr_accessor :pretty_content
25
+ attr_accessor :url
26
+ attr_accessor :created_at
27
+ attr_accessor :created_at_relative
28
+ attr_accessor :user
29
+
30
+ def comment? #:nodoc:
31
+ return @comment
32
+ end
33
+
34
+ def comment=(bool) #:nodoc:
35
+ @comment= bool
36
+ end
37
+
38
+ class << self
39
+ ##
40
+ # Given a hash that represents the JSON data from Jaiku
41
+ # for a message, this method will build and return a
42
+ # Rubyku::Message with those properties.
43
+ #
44
+ def build_message_from_json(json)
45
+ m = Rubyku::Message.new
46
+ #the jaiku json objects look differently depending on
47
+ #whether or not they are in response to another message.
48
+ #if they are a response, the comment_id field will be
49
+ #present rather than the id field. A few other distinctions
50
+ #are captured below.
51
+ unless json['comment_id']
52
+ m.comment= false
53
+ m.id = json['id']
54
+ else
55
+ m.comment= true
56
+ m.id = json['comment_id']
57
+ m.entry_title = json['entry_title']
58
+ m.pretty_content = json['pretty_content']
59
+ end
60
+
61
+ m.title = json['title']
62
+ m.content = json['content']
63
+ m.url = json['url']
64
+ m.created_at = DateTime.parse(json['created_at'])
65
+ m.created_at_relative = json['created_at_relative']
66
+ m.user = Rubyku::User.build_user_from_json(json['user'])
67
+
68
+ m
69
+ end
70
+ end
71
+ end
72
+
73
+ end
@@ -1,17 +1,28 @@
1
1
  module Rubyku
2
2
 
3
+ ##
4
+ # This is a utility class that handles communication with the Jaiku server.
5
+ #
3
6
  class Request
4
7
  class << self
5
-
8
+ ##
9
+ # This method uses the given url and credentials to retrieve
10
+ # JSON data from the Jaiku servers.
11
+ # returns: +Hash+ containing the JSON data.
12
+ #
6
13
  def retrieve_json_object(url_path, jaiku_credentials)
14
+ log = Rubyku::Settings.logger
15
+ log.info("About to request JSON from #{url_path}")
7
16
  url_path += jaiku_credentials.request_string
8
-
17
+ log.debug("Using full URL to fetch JSON: #{url_path}")
9
18
  url = URI.parse(url_path)
10
- req = Net::HTTP::Get.new(url.path)
19
+ req = Net::HTTP::Get.new(url.request_uri)
11
20
  res = Net::HTTP::Proxy(Rubyku::Settings.proxy_url, Rubyku::Settings.proxy_port) \
12
21
  .start(url.host, url.port) {|http|
13
22
  http.request(req)
14
23
  }
24
+ log.info("Jaiku JSON response returned HTTP code #{res.code}")
25
+ log.debug("About to return JSON: " + res.body)
15
26
  JSON(res.body)
16
27
  end
17
28
  end
@@ -1,4 +1,19 @@
1
1
  module Rubyku
2
+ ##
3
+ # This class acts as a centralized location for configurable items
4
+ # in rubyku. The configurable properties are as follows:
5
+ # - +logger+: a ruby logger object where all messages are logged.
6
+ # - +jaiku_credentials+: an instance of Rubyku::Credentials that is used
7
+ # throughout rubyku as the default credentials.
8
+ # - +proxy_url+: the url for an http proxy, if needed.
9
+ # - +proxy_port+: the port for an http proxy, if needed.
10
+ #
11
+ # The logger, by default, will log at Logger::INFO to logs/rubyku.log inside
12
+ # the project's source or gem folder. If you would like to integrate the rubyku
13
+ # logging statements into your own logs, simply replace the logger with your own
14
+ # at some point after including rubyku in your project.
15
+ # *WARNING*: a logger set to Logger::DEBUG will spit all kinds of user-sensitive
16
+ # information, and as such should only be used for testing.
2
17
  class Settings
3
18
  class << self
4
19
  #Yay logger! Default logger is initialized below. Override it
data/lib/rubyku/user.rb CHANGED
@@ -1,5 +1,13 @@
1
1
  module Rubyku
2
-
2
+ ##
3
+ # This class represents a user within the Jaiku system.
4
+ # It has the following attributes:
5
+ # - +avatar_url+: The url for locating the user's avatar picture.
6
+ # - +first_name+: The user's given first name.
7
+ # - +last_name+: The user's given last name.
8
+ # - +nick+: The user's unique username on Jaiku.
9
+ # - +jaiku_url+: The url where the user's jaiku account can be found.
10
+ # - +contacts+: A list of +Rubyku::User+ objects representing this user's contacts.
3
11
  class User
4
12
  attr_accessor :avatar_url
5
13
  attr_accessor :first_name
@@ -10,55 +18,69 @@ module Rubyku
10
18
 
11
19
  ##
12
20
  # Returns the list of contacts for the current user.
13
- # Contacts is the only property of User that is lazy-loaded.
14
- # This is because if it wasn't lazy-loaded, you'd be perpetually
15
- # creating user objects.
16
- #
17
- # @param jaiku_credentials<Rubyku::Credentials> the credentials to use
18
- # for authenticating with Jaiku. Defaults to any credentials set in <Rubyku::Settings>.
19
- #
20
- # @return <Array{Rubyku::User}> the users that this user follows on Jaiku.
21
+ # Contacts is the only property of User that is lazy-loaded.
22
+ # This is because if it wasn't lazy-loaded, you'd be perpetually
23
+ # creating user objects.
21
24
  #
22
- # @raise <Rubyku::UserNotFoundError> indicates that the user could not be found
23
- # in Jaiku.
24
- #
25
- # @raise <RubykuError> indicates that there was an error communicating
26
- # to the Jaiku servers.
25
+ # returns: +Array{Rubyku::User}+ the users that this user follows on Jaiku.
27
26
  #
28
27
  def contacts(jaiku_credentials=Rubyku::Settings.jaiku_credentials)
29
28
  log = Rubyku::Settings.logger
30
29
  unless @contacts
31
- log.info("contacts for user #{@username} requested - attempting to fetch.")
32
- @contacts = User.fetchContacts(@username, jaiku_credentials)
30
+ log.info("contacts for user #{@nick} requested - attempting to fetch.")
31
+ @contacts = Rubyku::User.fetch(@nick, jaiku_credentials).contacts
33
32
  end
34
33
 
35
34
  @contacts
36
35
  end
37
36
 
37
+ ##
38
+ # Returns the user's most recent updates.
39
+ # This method will hit the server every time, so cache the results if you need to.
40
+ #
41
+ # returns: +Array{Rubyku::Message}+ this user's most recent updates
42
+ #
43
+ def updates(jaiku_credentials=Rubyku::Settings.jaiku_credentials)
44
+ log = Rubyku::Settings.logger
45
+ log.info("Requesting updates from user #{@nick}")
46
+ url = "http://%s.jaiku.com/feed/json" % @nick
47
+ updates_json = Rubyku::Request.retrieve_json_object(url, jaiku_credentials)
48
+ updates_json['stream'].map { |m| Rubyku::Message.build_message_from_json(m) }
49
+ end
50
+
51
+ ##
52
+ # Returns the stream for this user (updates from their contacts, as they see
53
+ # on the home page).
54
+ # This method will hit the server everytime, so cache the results if you need to.
55
+ #
56
+ # returns: +Array{Rubyku::Message}+ the messages in this user's stream.
57
+ #
58
+ def stream(jaiku_credentials=Rubyku::Settings.jaiku_credentials)
59
+ log = Rubyku::Settings.logger
60
+ log.info("Requesting stream for user #{@nick}")
61
+ url = "http://%s.jaiku.com/contacts/feed/json" % @nick
62
+ stream_json = Rubyku::Request.retrieve_json_object(url, jaiku_credentials)
63
+ stream_json['stream'].map { |m| Rubyku::Message.build_message_from_json(m) }
64
+ end
65
+
38
66
  class << self
39
67
  ##
40
68
  # Retrieves a user's information from Jaiku.
41
- # All properties but contacts are loaded. @see <Rubyku::User.contacts>
42
- #
43
- # @param username<String> the user to fetch.
44
- #
45
- # @param jaiku_credentials<Rubyku::Credentials> the credentials to use
46
- # for authenticating with Jaiku. Defaults to any credentials set in <Rubyku::Defaults>.
47
- #
48
- # @return <Rubyku::User> the requested user.
49
69
  #
50
- # @raise <Rubyku::UserNotFoundError> indicates that the user could not be found
51
- # in Jaiku.
70
+ # returns: Rubyku::User the requested user.
52
71
  #
53
- # @raise <RubykuError> indicates that there was an error communicating
54
- # to the Jaiku servers.
55
- #
56
72
  def fetch(username,jaiku_credentials=Rubyku::Settings.jaiku_credentials)
57
73
  req_url = "http://%s.jaiku.com/json" % username
58
74
  json = Rubyku::Request.retrieve_json_object(req_url, jaiku_credentials)
59
75
  build_user_from_json(json)
60
76
  end
61
77
 
78
+ ##
79
+ # Given a hash representing the JSON data for a user from Jaiku,
80
+ # this method maps those JSON properties to a +Rubyku::User+ object
81
+ # and returns it.
82
+ # Contacts are loaded if present.
83
+ #
62
84
  def build_user_from_json(json)
63
85
  user = Rubyku::User.new
64
86
  user.nick= json['nick']
@@ -1,8 +1,8 @@
1
1
  module Rubyku #:nodoc:
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
- MINOR = 0
5
- TINY = 3
4
+ MINOR = 1
5
+ TINY = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
data/lib/rubyku.rb CHANGED
@@ -1,3 +1,5 @@
1
+ #:include:../README
2
+
1
3
  # Just to make our requires at the top of the gem a little easier.
2
4
  require 'pathname'
3
5
  $:.unshift(Pathname(__FILE__).dirname.expand_path)
@@ -6,9 +8,12 @@ require 'net/http'
6
8
  require 'logger'
7
9
  require 'rubygems'
8
10
  require 'json'
11
+ require 'date'
12
+
9
13
  #rubyku requires
10
14
  require 'rubyku/settings'
11
15
  require 'rubyku/errors'
16
+ require 'rubyku/message'
12
17
  require 'rubyku/user'
13
18
  require 'rubyku/credentials'
14
19
  require 'rubyku/version'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: duwanis-rubyku
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tommy Morgan
@@ -27,28 +27,29 @@ executables: []
27
27
 
28
28
  extensions: []
29
29
 
30
- extra_rdoc_files:
31
- - LICENSE
32
- - README
30
+ extra_rdoc_files: []
31
+
33
32
  files:
34
- - LICENSE
35
- - README
36
- - Rakefile
37
33
  - lib/rubyku.rb
38
- - lib/rubyku/version.rb
39
34
  - lib/rubyku/credentials.rb
40
- - lib/rubyku/settings.rb
41
- - lib/rubyku/user.rb
42
35
  - lib/rubyku/errors.rb
36
+ - lib/rubyku/message.rb
43
37
  - lib/rubyku/request.rb
44
- - test/test_helper.rb
45
- - test/test_rubyku.rb
38
+ - lib/rubyku/settings.rb
39
+ - lib/rubyku/user.rb
40
+ - lib/rubyku/version.rb
41
+ - LICENSE
42
+ - README
43
+ - logs/
46
44
  has_rdoc: true
47
45
  homepage: http://github.com/duwanis/rubyku
48
46
  post_install_message:
49
47
  rdoc_options:
48
+ - --title
49
+ - Rubyku - Jaiku for Ruby
50
50
  - --main
51
- - README
51
+ - lib/rubyku.rb
52
+ - --line-numbers
52
53
  require_paths:
53
54
  - lib
54
55
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -70,6 +71,5 @@ rubygems_version: 1.0.1
70
71
  signing_key:
71
72
  specification_version: 2
72
73
  summary: A Ruby API for accessing Jaiku.
73
- test_files:
74
- - test/test_helper.rb
75
- - test/test_rubyku.rb
74
+ test_files: []
75
+
data/Rakefile DELETED
@@ -1,7 +0,0 @@
1
- task :build_gem do
2
- system("gem build rubyku.gemspec")
3
- end
4
-
5
- task :prepare_commit do
6
- system("rm logs/*")
7
- end
data/test/test_helper.rb DELETED
@@ -1,2 +0,0 @@
1
- require 'test/unit'
2
- require File.dirname(__FILE__) + '/../lib/rubyku'
data/test/test_rubyku.rb DELETED
@@ -1,11 +0,0 @@
1
- require File.dirname(__FILE__) + '/test_helper.rb'
2
-
3
- class TestRubyku < Test::Unit::TestCase
4
-
5
- def setup
6
- end
7
-
8
- def test_truth
9
- assert true
10
- end
11
- end