ubiquitously 0.0.1.5 → 0.0.1.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []