ubiquitously 0.0.1.5 → 0.0.1.6

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.
@@ -1,3 +1,50 @@
1
1
  # [Ubiquitously](http://ubiquitously.me/)
2
2
 
3
- > Making it easy for you to be everywhere, even if there's no API
3
+ > Making it easy for you to be everywhere, even if there's no API
4
+
5
+ ## Usage
6
+
7
+ ### Install
8
+
9
+ sudo gem install ubiquitously
10
+
11
+ ### Run Tests
12
+
13
+ Fill out `test/config.yml` with your credentials for the different services, then run
14
+
15
+ rake test
16
+
17
+ ### Register for the services you haven't already
18
+
19
+ First edit the config file with a username, password, and other fields that all the systems might have. Then run this
20
+
21
+ rake ubiquitously:me
22
+
23
+ ### Automatically Post to Services
24
+
25
+ require 'rubygems'
26
+ require 'ubiquitously'
27
+
28
+ # dzone
29
+ Ubiquitously::Dzone::Post.create(
30
+ :title => "A Dzone Post!",
31
+ :description => "Dzone does not let you edit or delete posts once you submit them, so be careful!",
32
+ :tags => ["dzone", "web 2.0"]
33
+ )
34
+
35
+ ## How it works
36
+
37
+ Everything is built around [Mechanize](http://mechanize.rubyforge.org/mechanize/GUIDE_rdoc.html) and [Nokogiri](http://nokogiri.org/tutorials/parsing_an_html_xml_document.html), both led by [Aaron Patterson](http://tenderlovemaking.com/).
38
+
39
+ Many social bookmarking services do not have API's in order to prevent spammers from ruining their system. But what about for those of us that actually create content several times a day and want automation? We're out of luck.
40
+
41
+ So Ubiquitously creates a simple, RESTful API around some services I need to publish to now, and hopefully it will grow as you guys need more. The goal is to be semi-low-level and not to provide a full featured api to a service, as some services already have very well-done API's in Ruby.
42
+
43
+ ## Other Possible Services (and Resources)
44
+
45
+ - [http://www.iwoodpecker.com/collection-of-70-best-social-bookmarking-sites-with-pr-and-alexa/](http://www.iwoodpecker.com/collection-of-70-best-social-bookmarking-sites-with-pr-and-alexa/)
46
+ - buzz.yahoo.com
47
+ - http://www.wikio.com/about-us
48
+ - http://designbump.com/
49
+ - http://scriptandstyle.com/submit
50
+ - http://www.stumpedia.com/submitlink.php
data/Rakefile CHANGED
@@ -5,7 +5,7 @@ require 'rake/gempackagetask'
5
5
  # http://docs.rubygems.org/read/chapter/20
6
6
  spec = Gem::Specification.new do |s|
7
7
  s.name = "ubiquitously"
8
- s.version = "0.0.1.5"
8
+ s.version = "0.0.1.6"
9
9
  s.author = "Lance Pollard"
10
10
  s.summary = "Ubiquitously: Making it easy for you to be everywhere, even if there's no API"
11
11
  s.homepage = "http://github.com/viatropos/ubiquitously"
@@ -66,3 +66,13 @@ end
66
66
  task :yank do
67
67
  `gem yank #{spec.name} -v #{spec.version}`
68
68
  end
69
+
70
+ desc 'run unit tests'
71
+ task :test do
72
+ Dir["test/**/*"].each do |file|
73
+ next unless File.extname(file) == ".rb"
74
+ next unless File.basename(file) =~ /test_/
75
+ next if File.basename(file) =~ /test_helper/
76
+ require file
77
+ end
78
+ end
@@ -0,0 +1,37 @@
1
+ class Hash
2
+ def recursively_symbolize_keys!
3
+ self.symbolize_keys!
4
+ self.values.each do |v|
5
+ if v.is_a? Hash
6
+ v.recursively_symbolize_keys!
7
+ elsif v.is_a? Array
8
+ v.recursively_symbolize_keys!
9
+ end
10
+ end
11
+ self
12
+ end
13
+
14
+ def symbolize_keys
15
+ inject({}) do |options, (key, value)|
16
+ options[(key.to_sym rescue key) || key] = value
17
+ options
18
+ end
19
+ end
20
+
21
+ # Destructively convert all keys to symbols.
22
+ def symbolize_keys!
23
+ self.replace(self.symbolize_keys)
24
+ end
25
+ end
26
+
27
+ class Array
28
+ def recursively_symbolize_keys!
29
+ self.each do |item|
30
+ if item.is_a? Hash
31
+ item.recursively_symbolize_keys!
32
+ elsif item.is_a? Array
33
+ item.recursively_symbolize_keys!
34
+ end
35
+ end
36
+ end
37
+ end
@@ -1,28 +1,46 @@
1
1
  require 'rubygems'
2
+ require 'open-uri'
3
+ require 'cgi'
2
4
  require 'yaml'
5
+ require 'json'
6
+ require 'nokogiri'
7
+ require 'mechanize'
8
+ require 'highline/import'
9
+ require 'logger'
3
10
  require 'active_support'
11
+ require 'active_model'
4
12
 
5
13
  this = File.dirname(__FILE__)
6
- require File.join(this, "ext.rb")
14
+ require "#{this}/ext"
15
+ Dir["#{this}/ubiquitously/mixins/*"].each { |c| require c }
16
+ require "#{this}/ubiquitously/base"
7
17
 
8
- module Compressible
9
-
10
- KEYS = {
11
- :css => :stylesheet,
12
- :stylesheet => :css,
13
- :js => :javascript,
14
- :javascript => :js
15
- }
16
-
17
- end
18
-
19
- Dir["#{this}/compressible/*"].each { |c| require c }
18
+ module Ubiquitously
19
+ class SettingsError < StandardError; end
20
+ class AuthenticationError < StandardError; end
21
+ class DuplicateError < StandardError; end
20
22
 
21
- Compressible.send(:include, Compressible::Configurable)
22
- Compressible.send(:include, Compressible::Assetable)
23
- Compressible.send(:include, Compressible::Readable)
24
- Compressible.send(:include, Compressible::Writable)
25
-
26
- def Compressible(*args, &block)
27
- Compressible.define!(*args, &block)
23
+ class << self
24
+ attr_accessor :config
25
+
26
+ def configure(value)
27
+ self.config = value.is_a?(String) ? YAML.load_file(value) : value
28
+ end
29
+
30
+ def key(path)
31
+ result = self.config
32
+ path.to_s.split(".").each { |node| result = result[node.to_s] if result }
33
+ result.to_s
34
+ end
35
+
36
+ def credentials(service)
37
+ result = key(service)
38
+ unless result && result.has_key?("key") && result.has_key?("secret")
39
+ raise SettingsError.new("Please specify both a key and secret for ':#{service}'")
40
+ end
41
+ result
42
+ end
43
+ end
28
44
  end
45
+
46
+ Dir["#{this}/ubiquitously/*"].each { |c| require c unless File.directory?(c) }
@@ -0,0 +1,56 @@
1
+ module Ubiquitously
2
+ module Base
3
+ class User
4
+ include ActiveModel::Validations
5
+ include ActiveModel::Serialization
6
+ include Ubiquitously::Resourceful
7
+
8
+ attr_accessor :agent, :username, :password
9
+
10
+ validates_presence_of :username, :password
11
+
12
+ def initialize(attributes = {})
13
+ attributes = attributes.symbolize_keys
14
+
15
+ attributes[:username] ||= Ubiquitously.key("#{service_name}.key")
16
+ attributes[:password] ||= Ubiquitously.key("#{service_name}.secret")
17
+
18
+ @logged_in = false
19
+
20
+ super(attributes)
21
+
22
+ self.agent = Mechanize.new
23
+ # self.agent.log = Logger.new(STDOUT)
24
+ self.agent.user_agent = "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_2; ru-ru) AppleWebKit/533.2+ (KHTML, like Gecko) Version/4.0.4 Safari/531.21.10"
25
+ end
26
+
27
+ def logged_in?
28
+ @logged_in == true
29
+ end
30
+ end
31
+
32
+ class Post
33
+ include ActiveModel::Validations
34
+ include ActiveModel::Serialization
35
+ include Ubiquitously::Resourceful
36
+
37
+ attr_accessor :title, :url, :description, :tags, :categories, :service_url, :user
38
+
39
+ def user
40
+ @user ||= "Ubiquitously::#{service_name.titleize}::User".constantize.new
41
+ end
42
+
43
+ def agent
44
+ user.agent
45
+ end
46
+
47
+ class << self
48
+ def create(options = {})
49
+ record = new(options)
50
+ record.save
51
+ record
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,111 @@
1
+ module Ubiquitously
2
+ module Dzone
3
+ class User < Ubiquitously::Base::User
4
+ def login
5
+ return true if logged_in?
6
+
7
+ page = agent.get("http://www.dzone.com/links/loginLightbox.html")
8
+ form = page.form_with(:action => "/links/j_acegi_security_check")
9
+ form["j_username"] = username
10
+ form["j_password"] = password
11
+ page = form.submit
12
+
13
+ @logged_in = (page.body !~ /Invalid username or password/i).nil?
14
+
15
+ unless @logged_in
16
+ raise AuthenticationError.new("Invalid username or password for #{service_name.titleize}")
17
+ end
18
+
19
+ @logged_in
20
+ end
21
+
22
+ def create
23
+
24
+ end
25
+ end
26
+
27
+ class Post < Ubiquitously::Base::Post
28
+ validates_presence_of :url, :title, :description, :service_url
29
+
30
+ class << self
31
+
32
+ def first(url)
33
+ find(url).first
34
+ end
35
+
36
+ def last(url)
37
+ find(url).last
38
+ end
39
+
40
+ def find(url)
41
+ query = CGI.escape(url.gsub(/http(s)?\:\/\//, ""))
42
+ search = "http://www.dzone.com/links/search.html?query=#{query}"
43
+ html = Nokogiri::HTML(open(search).read)
44
+ records = []
45
+
46
+ html.css(".linkblock").each do |node|
47
+ link = node.css(".thumb a").first["href"]
48
+ header = node.css(".details h3 a").first
49
+ title = header.text
50
+ service_url = header["href"]
51
+ records << Ubiquitously::Dzone::Post.new(
52
+ :url => link,
53
+ :title => title,
54
+ :service_url => service_url
55
+ )
56
+ end
57
+
58
+ records
59
+ end
60
+
61
+ # http://www.dzone.com/links/feed/user/<user_id>/rss.xml
62
+ # check to see if dzone already has the url
63
+ def new_record?(url, throw_error = false)
64
+ exists = !find(url).blank?
65
+ raise DuplicateError.new("DZone already links to #{url}") if throw_error && exists
66
+ exists
67
+ end
68
+ end
69
+
70
+ def save(options = {})
71
+ return false unless valid? && new_record?
72
+
73
+ user.login
74
+
75
+ # url
76
+ page = agent.get("http://www.dzone.com/links/add.html")
77
+ form = page.form_with(:action => "/links/add.html")
78
+
79
+ accepted_tags = []
80
+
81
+ form.checkboxes_with(:name => "tags").each do |tag|
82
+ accepted_tags << tag.value.to_s
83
+ end
84
+
85
+ unaccepted_tags = tags.select { |tag| !accepted_tags.include?(tag) }
86
+
87
+ if unaccepted_tags.length > 0
88
+ raise ArgumentError.new("DZone doesn't accept these tags: #{unaccepted_tags.inspect}, they want these:\n#{accepted_tags.inspect}")
89
+ end
90
+
91
+ form["title"] = title
92
+ form["url"] = url
93
+ form["description"] = description
94
+
95
+ form.checkboxes_with(:name => "tags").each do |checkbox|
96
+ checkbox.check if tags.include?(checkbox.value)
97
+ end
98
+
99
+ unless options[:debug] == true
100
+ page = form.submit
101
+ end
102
+
103
+ true
104
+ end
105
+
106
+ def new_record?
107
+ self.class.new_record?(url)
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,43 @@
1
+ module Ubiquitously
2
+ module Faves
3
+ class User < Ubiquitously::Base::User
4
+ def login
5
+ page = agent.get("https://secure.faves.com/signIn")
6
+ form = page.forms.detect {|form| form.form_node["id"] == "signInBox"}
7
+ form["rUsername"] = username
8
+ form["rPassword"] = password
9
+ page = form.submit
10
+
11
+ @logged_in = (page.title =~ /Sign In/i).nil?
12
+
13
+ unless @logged_in
14
+ raise AuthenticationError.new("Invalid username or password for #{service_name.titleize}")
15
+ end
16
+
17
+ @logged_in
18
+ end
19
+ end
20
+
21
+ class Post < Ubiquitously::Base::Post
22
+ validates_presence_of :url, :title, :description, :tags
23
+
24
+ def save
25
+ return false unless valid?
26
+
27
+ user.login
28
+
29
+ page = agent.get("http://faves.com/createdot.aspx")
30
+ form = page.form_with(:name => "createDotForm")
31
+ form["noteText"] = description
32
+ form["urlText"] = url
33
+ form["subjectText"] = title
34
+ form["tagsText"] = tags.join(", ")
35
+ #form["rateSelect"]
36
+
37
+ unless options[:debug] == true
38
+ page = form.submit
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,11 @@
1
+ module Ubiquitously
2
+ module MisterWong
3
+ class User
4
+
5
+ end
6
+
7
+ class Post
8
+
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,50 @@
1
+ module Ubiquitously
2
+ module Resourceful
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ base.send :include, InstanceMethods
6
+ end
7
+
8
+ module ClassMethods
9
+ def service_name
10
+ self.to_s.split("::")[1].underscore.downcase
11
+ end
12
+
13
+ def required_arguments(*args)
14
+ @required_arguments = args unless args.blank?
15
+ @required_arguments ||= []
16
+ @required_arguments
17
+ end
18
+ alias requires required_arguments
19
+
20
+ def assert_required_arguments(options)
21
+ missing = []
22
+ required_arguments.each do |arg|
23
+ missing << arg unless options.has_key?(arg)
24
+ end
25
+ unless missing.blank?
26
+ raise ArgumentError.new("#{service_name.titleize} requires #{missing.join(", and")}")
27
+ end
28
+
29
+ missing.blank?
30
+ end
31
+ end
32
+
33
+ module InstanceMethods
34
+
35
+ def initialize(attributes = {})
36
+ attributes.each do |key, value|
37
+ self.send("#{key.to_s}=", value) if self.respond_to?(key)
38
+ end
39
+ end
40
+
41
+ def service_name
42
+ self.class.service_name
43
+ end
44
+
45
+ def assert_required_arguments(options)
46
+ self.class.assert_required_arguments(options)
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,66 @@
1
+ module Ubiquitously
2
+ module Mixx
3
+ class User < Ubiquitously::Base::User
4
+ def login
5
+ return true if logged_in?
6
+
7
+ page = agent.get("https://www.mixx.com/")
8
+ form = page.form_with(:action => "https://www.mixx.com/save_login")
9
+ form["user[loginid]"] = username
10
+ form["user[password]"] = password
11
+ page = form.submit
12
+
13
+ @logged_in = (page.body =~ /login was unsuccessful/i).nil?
14
+
15
+ unless @logged_in
16
+ raise AuthenticationError.new("Invalid username or password for #{service_name.titleize}")
17
+ end
18
+
19
+ @logged_in
20
+ end
21
+ end
22
+
23
+ class Post < Ubiquitously::Base::Post
24
+ def save
25
+ return false unless valid?
26
+
27
+ user.login
28
+
29
+ page = agent.get("http://www.mixx.com/submit")
30
+ form = page.form_with(:action => "http://www.mixx.com/submit/step2")
31
+ form["thingy[page_url]"] = url
32
+ page = form.submit
33
+
34
+ # last page
35
+ form = page.form_with(:action => "http://www.mixx.com/submit/save")
36
+
37
+ # captcha
38
+ iframe_url = page.parser.css("li.captcha iframe").first["src"]
39
+ params = iframe_url.split("?").last
40
+ captcha_iframe = agent.click(page.iframes.first)
41
+ captcha_form = captcha_iframe.forms.first
42
+ captcha_image = captcha_iframe.parser.css("img").first["src"]
43
+ # open browser with captcha image
44
+ system("open", "http://api.recaptcha.net/#{captcha_image}")
45
+ # enter captcha response in terminal
46
+ captcha_says = ask("Enter Captcha from Browser Image: ") { |q| q.echo = true }
47
+ captcha_form["recaptcha_response_field"] = captcha_says
48
+ # submit captcha
49
+ captcha_form.action = "http://www.google.com/recaptcha/api/noscript?#{params}"
50
+ captcha_response = captcha_form.submit
51
+ # grab secret
52
+ captcha_response = captcha_response.parser.css("textarea").first.text
53
+
54
+ # submit post
55
+ form = page.form_with(:action => "http://www.mixx.com/submit/save")
56
+ form["thingy[title]"] = title
57
+ form["thingy[description]"] = description if description
58
+ form["thingy[new_tags]"] = tags if tags
59
+ form["recaptcha_challenge_field"] = captcha_response
60
+ form["recaptcha_response_field"] = captcha_says
61
+
62
+ form.submit
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,54 @@
1
+ module Ubiquitously
2
+ module Newsvine
3
+ class User < Ubiquitously::Base::User
4
+ def login
5
+ return true if logged_in?
6
+
7
+ page = agent.get("https://www.newsvine.com/_nv/accounts/login")
8
+ form = page.form_with(:action => "https://www.newsvine.com/_nv/api/accounts/login")
9
+ form["email"] = username
10
+ form["password"] = password
11
+ page = form.submit
12
+
13
+ # No match. Please try again
14
+ @logged_in = (page.title =~ /Log in/i).nil?
15
+
16
+ unless @logged_in
17
+ raise AuthenticationError.new("Invalid username or password for #{service_name.titleize}")
18
+ end
19
+
20
+ @logged_in
21
+ end
22
+ end
23
+
24
+ class Post < Ubiquitously::Base::Post
25
+ validates_presence_of :url, :title
26
+
27
+ def save(options = {})
28
+ return false unless valid?
29
+
30
+ user.login
31
+
32
+ page = agent.get("http://www.newsvine.com/_tools/seed")
33
+ form = page.form_with(:action => "http://www.newsvine.com/_action/tools/saveLink")
34
+
35
+ form["url"] = url
36
+ form["headline"] = title
37
+ form.radiobuttons_with(:name => "newsType").each do |button|
38
+ button.check if button.value == "x"
39
+ end
40
+ form.field_with(:name => "categoryTag").options.each do |option|
41
+ option.select if option.value == "technology"
42
+ end
43
+ form["blurb"] = description
44
+ form["tags"] = tags.join(", ")
45
+
46
+ unless options[:debug] == true
47
+ page = form.submit
48
+ end
49
+
50
+ true
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,69 @@
1
+ module Ubiquitously
2
+ module Propeller
3
+ class User < Ubiquitously::Base::User
4
+ def login
5
+ puts "LOGGING IN"
6
+ page = agent.get("http://www.propeller.com/signin/")
7
+ form = page.forms.detect {|form| form.form_node["class"] == "ajax-form"}
8
+ form["member_name"] = username
9
+ form["password"] = password
10
+ form["submit"] = "sign in" # require to get around the ajax
11
+ page = form.submit
12
+ puts "DONE"
13
+ @logged_in = (page.body =~ /Invalid member name or password/i).nil? && (page.body =~ /ajax-form/).nil?
14
+
15
+ unless @logged_in
16
+ raise AuthenticationError.new("Invalid username or password for #{service_name.titleize}")
17
+ end
18
+
19
+ @logged_in
20
+ end
21
+ end
22
+
23
+ class Post < Ubiquitously::Base::Post
24
+ # title max == 150
25
+ validates_presence_of :url, :title, :tags, :description
26
+
27
+ def save
28
+ return false unless valid?
29
+
30
+ user.login
31
+
32
+ # url
33
+ page = agent.get("http://www.propeller.com/story/submit/")
34
+ form = page.forms.detect {|form| form.form_node["method"].downcase == "post"}
35
+ form["url"] = url
36
+ puts "SUBMIT FORM"
37
+ # details
38
+ # http://www.propeller.com/story/submit/content/
39
+ page = form.submit
40
+ form = page.forms.detect {|form| form.form_node["method"].downcase == "post"}
41
+ puts "DETAILS"
42
+ form.radiobuttons_with(:name => "title_multi").each do |button|
43
+ button.check if button.value == "-1"
44
+ end
45
+
46
+ form["title_multi_text"] = title
47
+ form["description"] = description
48
+ # separate by space, multi words are underscored
49
+ form["user_tags"] = tags.map {|tag| tag.underscore.gsub(/[\s|-]+/, "_")}.join(" ")
50
+
51
+ form.radiobuttons_with(:name => "category").each do |button|
52
+ button.check if button.value.to_s == "18"
53
+ end
54
+
55
+ # http://www.propeller.com/story/submit/preview/
56
+ page = form.submit
57
+ puts "SUBMIT DETAILS"
58
+ # approve
59
+ page.forms[1].submit
60
+
61
+ unless options[:debug] == true
62
+ page = form.submit
63
+ end
64
+
65
+ true
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,46 @@
1
+ module Ubiquitously
2
+ module Reddit
3
+ class User < Ubiquitously::Base::User
4
+ def login
5
+ return true if logged_in?
6
+
7
+ page = agent.get("http://www.reddit.com/")
8
+ form = page.form_with(:action => "http://www.reddit.com/post/login")
9
+ form["user"] = username
10
+ form["passwd"] = password
11
+ page = form.submit
12
+
13
+ @logged_in = (page.title =~ /login or register/i).nil?
14
+
15
+ unless @logged_in
16
+ raise AuthenticationError.new("Invalid username or password for #{service_name.titleize}")
17
+ end
18
+
19
+ @logged_in
20
+ end
21
+ end
22
+
23
+ class Post < Ubiquitously::Base::Post
24
+ validates_presence_of :url, :title
25
+
26
+ def save(options = {})
27
+ return false unless valid?
28
+
29
+ user.login
30
+
31
+ page = agent.get("http://www.reddit.com/submit")
32
+ form = page.forms.detect {|form| form.form_node["id"] == "newlink"}
33
+ form["title"] = title
34
+ form["url"] = url
35
+ form["id"] = "#newlink"
36
+ form.action = "http://www.reddit.com/api/submit"
37
+ headers = {
38
+ "Content-Type" => "application/json"
39
+ }
40
+ unless options[:debug] == true
41
+ page = form.submit(nil, headers)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,11 @@
1
+ module Ubiquitously
2
+ module Sphinn
3
+ class User
4
+
5
+ end
6
+
7
+ class Post
8
+
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,61 @@
1
+ module Ubiquitously
2
+ module StumbleUpon
3
+ class User < Ubiquitously::Base::User
4
+ def login
5
+ page = agent.get("http://www.stumbleupon.com/login.php")
6
+ form = page.form_with(:name => "formLogin")
7
+ form["username"] = username
8
+ form["password"] = password
9
+ page = form.submit
10
+
11
+ @logged_in = (page.body =~ /Invalid username/i).nil?
12
+
13
+ unless @logged_in
14
+ raise AuthenticationError.new("Invalid username or password for #{service_name.titleize}")
15
+ end
16
+
17
+ @logged_in
18
+ end
19
+ end
20
+
21
+ class Post < Ubiquitously::Base::Post
22
+ def save
23
+ return false unless valid?
24
+
25
+ user.login
26
+
27
+ page = agent.get("http://www.stumbleupon.com/submit?url=#{url}&title=#{title}")
28
+ form = page.forms.first
29
+ form["topic"] = title
30
+ form["comment"] = description
31
+ form.radiobuttons_with(:name => "sfw").first.check
32
+ page = agent.submit(form)
33
+
34
+ # add tags
35
+ page = agent.get("http://www.stumbleupon.com/favorites/")
36
+ # get key properties
37
+ token = page.parser.css("div#wrapperContent").first["class"]
38
+ var = page.parser.css("li.listLi var").first
39
+ comment_id = var["id"]
40
+ public_id = var["class"]
41
+
42
+ # post to hidden api
43
+ url = "http://www.stumbleupon.com/ajax/edit/comment"
44
+ params = {
45
+ "syndicate_fb" =>"syndicate_fb",
46
+ "title" => title,
47
+ "token" => token,
48
+ "sticky_post" => "0",
49
+ "review" => description,
50
+ "tags" => tags.join(", "),
51
+ "publicid" => public_id,
52
+ "syndicate_tw" => "syndicate_tw",
53
+ "commentid" => comment_id,
54
+ "keep_date" => "1"
55
+ }
56
+
57
+ page = agent.post(url, params)
58
+ end
59
+ end
60
+ end
61
+ end
@@ -1,2 +1,18 @@
1
1
  dzone:
2
-
2
+ key: viatropos
3
+ secret: "w!sd0m[:227]"
4
+ reddit:
5
+ key: viatropos
6
+ secret: "w!sd0m[:227]"
7
+ stumble_upon:
8
+ key: viatropos
9
+ secret: "tarq1986"
10
+ faves:
11
+ key: viatropos
12
+ secret: tarq1986
13
+ newsvine:
14
+ key: viatropos
15
+ secret: tarq1986
16
+ propeller:
17
+ key: viatropos
18
+ secret: tarq1986
@@ -0,0 +1,43 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ module Ubiquitously
4
+ class DzoneTest < ActiveSupport::TestCase
5
+ context "Dzone::User" do
6
+ setup do
7
+ @user = Ubiquitously::Dzone::User.new
8
+ end
9
+
10
+ context "login" do
11
+ should "raise informative error if invalid password" do
12
+ @user.password = "bad password"
13
+ assert_raises(Ubiquitously::AuthenticationError) do
14
+ @user.login
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ context "Dzone::Post" do
21
+ setup do
22
+ @post = Ubiquitously::Dzone::Post.new
23
+ end
24
+
25
+ should "raise error if post exists already" do
26
+ assert_raises(Ubiquitously::DuplicateError) do
27
+ Ubiquitously::Dzone::Post.new_record?("http://www.google.com", true)
28
+ end
29
+ end
30
+
31
+ should "create a post" do
32
+ # http://www.dzone.com/links/buttons.jsp
33
+ assert Ubiquitously::Dzone::Post.create(
34
+ :debug => true,
35
+ :title => "A Title",
36
+ :description => "A Description",
37
+ :tags => ["usability", "ruby", "web services", "open source"],
38
+ :url => "http://example.com/abcdef"
39
+ )
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,42 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+ require 'restclient'
3
+ module Ubiquitously
4
+ class FavesTest < ActiveSupport::TestCase
5
+ context "Faves::User" do
6
+ setup do
7
+ @user = Ubiquitously::Faves::User.new
8
+ end
9
+
10
+ context "login" do
11
+ should "raise informative error if invalid password" do
12
+ @user.password = "bad password"
13
+ assert_raises(Ubiquitously::AuthenticationError) do
14
+ @user.login
15
+ end
16
+ end
17
+
18
+ should "login successfully if valid credentials" do
19
+ assert_equal true, @user.login
20
+ end
21
+ end
22
+ end
23
+ =begin
24
+ context "Faves::Post" do
25
+ setup do
26
+ @post = Ubiquitously::Faves::Post.new(
27
+ :debug => true,
28
+ :title => "A Title",
29
+ :description => "A Description",
30
+ :tags => ["usability", "ruby", "web services", "open source"],
31
+ :url => "http://example.com/abcdef",
32
+ :user => Ubiquitously::Faves::User.new
33
+ )
34
+ end
35
+
36
+ should "create a post" do
37
+ assert @post.save
38
+ end
39
+ end
40
+ =end
41
+ end
42
+ end
@@ -1,7 +1,13 @@
1
- require "test/unit"
2
1
  require "rubygems"
2
+ require 'active_support'
3
3
  require "ruby-debug"
4
+ gem 'test-unit'
5
+ require "test/unit"
4
6
  require 'active_support'
7
+ require 'active_support/test_case'
5
8
  require 'shoulda'
9
+ require 'rr'
6
10
 
7
11
  require File.dirname(__FILE__) + '/../lib/ubiquitously'
12
+
13
+ Ubiquitously.configure("test/config.yml")
@@ -0,0 +1,42 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ module Ubiquitously
4
+ class NewsvineTest < ActiveSupport::TestCase
5
+ context "Newsvine::User" do
6
+ setup do
7
+ @user = Ubiquitously::Newsvine::User.new
8
+ end
9
+
10
+ context "login" do
11
+ should "raise informative error if invalid password" do
12
+ @user.password = "bad password"
13
+ assert_raises(Ubiquitously::AuthenticationError) do
14
+ @user.login
15
+ end
16
+ assert_equal false, @user.logged_in?
17
+ end
18
+
19
+ should "login successfully if valid credentials" do
20
+ assert_equal true, @user.login
21
+ assert_equal true, @user.logged_in?
22
+ end
23
+ end
24
+ end
25
+
26
+ context "Newsvine::Post" do
27
+ setup do
28
+ @post = Ubiquitously::Newsvine::Post.new(
29
+ :title => "A Title",
30
+ :description => "A Description",
31
+ :tags => ["usability", "ruby", "web services", "open source"],
32
+ :url => "http://example.com/abcdef",
33
+ :user => Ubiquitously::Newsvine::User.new
34
+ )
35
+ end
36
+
37
+ should "create a post" do
38
+ assert @post.save(:debug => true)
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,43 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ module Ubiquitously
4
+ class PropellerTest < ActiveSupport::TestCase
5
+ context "Propeller::User" do
6
+ setup do
7
+ @user = Ubiquitously::Propeller::User.new
8
+ end
9
+
10
+ context "login" do
11
+ should "raise informative error if invalid password" do
12
+ @user.password = "bad password"
13
+ assert_raises(Ubiquitously::AuthenticationError) do
14
+ @user.login
15
+ end
16
+ assert_equal false, @user.logged_in?
17
+ end
18
+
19
+ should "login successfully if valid credentials" do
20
+ assert_equal true, @user.login
21
+ assert_equal true, @user.logged_in?
22
+ end
23
+ end
24
+
25
+ context "Propeller::Post" do
26
+ setup do
27
+ @post = Ubiquitously::Propeller::Post.new(
28
+ :debug => true,
29
+ :title => "A Title",
30
+ :description => "A Description",
31
+ :tags => ["usability", "ruby", "web services", "open source"],
32
+ :url => "http://example.com/abcdef"
33
+ )
34
+ end
35
+
36
+ should "create a post" do
37
+ assert @post.save(:debug => true)
38
+ end
39
+ end
40
+ end
41
+
42
+ end
43
+ end
@@ -0,0 +1,32 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ module Ubiquitously
4
+ class RedditTest < ActiveSupport::TestCase
5
+ context "Reddit::User" do
6
+ setup do
7
+ @user = Ubiquitously::Reddit::User.new
8
+ end
9
+
10
+ context "login" do
11
+ should "raise informative error if invalid password" do
12
+ @user.password = "bad password"
13
+ assert_raises(Ubiquitously::AuthenticationError) do
14
+ @user.login
15
+ end
16
+ assert_equal false, @user.logged_in?
17
+ end
18
+
19
+ should "login successfully if valid credentials" do
20
+ assert_equal true, @user.login
21
+ assert_equal true, @user.logged_in?
22
+ end
23
+ end
24
+ end
25
+
26
+ context "Reddit::Post" do
27
+ setup do
28
+ @post = Ubiquitously::Reddit::Post.new
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,32 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ module Ubiquitously
4
+ class StumbleUponTest < ActiveSupport::TestCase
5
+ context "StumbleUpon::User" do
6
+ setup do
7
+ @user = Ubiquitously::StumbleUpon::User.new
8
+ end
9
+
10
+ context "login" do
11
+ should "raise informative error if invalid password" do
12
+ @user.password = "bad password"
13
+ assert_raises(Ubiquitously::AuthenticationError) do
14
+ @user.login
15
+ end
16
+ assert_equal false, @user.logged_in?
17
+ end
18
+
19
+ should "login successfully if valid credentials" do
20
+ assert_equal true, @user.login
21
+ assert_equal true, @user.logged_in?
22
+ end
23
+ end
24
+ end
25
+
26
+ context "StumbleUpon::Post" do
27
+ setup do
28
+ @post = Ubiquitously::StumbleUpon::Post.new
29
+ end
30
+ end
31
+ end
32
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ubiquitously
3
3
  version: !ruby/object:Gem::Version
4
- hash: 65
4
+ hash: 71
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
9
  - 1
10
- - 5
11
- version: 0.0.1.5
10
+ - 6
11
+ version: 0.0.1.6
12
12
  platform: ruby
13
13
  authors:
14
14
  - Lance Pollard
@@ -48,10 +48,28 @@ files:
48
48
  - Rakefile
49
49
  - init.rb
50
50
  - MIT-LICENSE
51
+ - lib/ext.rb
52
+ - lib/ubiquitously/base.rb
53
+ - lib/ubiquitously/dzone.rb
54
+ - lib/ubiquitously/faves.rb
55
+ - lib/ubiquitously/mister_wong.rb
56
+ - lib/ubiquitously/mixins/resourceful.rb
57
+ - lib/ubiquitously/mixx.rb
58
+ - lib/ubiquitously/newsvine.rb
59
+ - lib/ubiquitously/propeller.rb
60
+ - lib/ubiquitously/reddit.rb
61
+ - lib/ubiquitously/sphinn.rb
62
+ - lib/ubiquitously/stumble_upon.rb
51
63
  - lib/ubiquitously.rb
52
64
  - rails/init.rb
53
65
  - test/config.yml
66
+ - test/test_dzone.rb
67
+ - test/test_faves.rb
54
68
  - test/test_helper.rb
69
+ - test/test_newsvine.rb
70
+ - test/test_propeller.rb
71
+ - test/test_reddit.rb
72
+ - test/test_stumble_upon.rb
55
73
  has_rdoc: true
56
74
  homepage: http://github.com/viatropos/ubiquitously
57
75
  licenses: []