csexton-twitter_archive 0.0.1

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/History ADDED
@@ -0,0 +1,4 @@
1
+ == 0.0.1 2008-12-28
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ (The MIT License)
2
+
3
+ Copyright (c) 2009 Christopher Sexton
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ 'Software'), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Manifest ADDED
@@ -0,0 +1,29 @@
1
+ bin/twitter_archive
2
+ CHANGELOG
3
+ config/test.yml
4
+ lib/twitter_archive/backends/blogger/base.rb
5
+ lib/twitter_archive/backends/blogger/blogger.rb
6
+ lib/twitter_archive/backends/blogger/post_body.html.erb
7
+ lib/twitter_archive/backends/blogger/README
8
+ lib/twitter_archive/backends/blogger_archive.rb
9
+ lib/twitter_archive/backends/yaml_archive.rb
10
+ lib/twitter_archive/base.rb
11
+ lib/twitter_archive/runner.rb
12
+ lib/twitter_archive/version.rb
13
+ lib/twitter_archive.rb
14
+ LICENSE
15
+ Manifest
16
+ Rakefile
17
+ README.rdoc
18
+ script/console
19
+ script/destroy
20
+ script/generate
21
+ spec/backends/blogger_archive_spec.rb
22
+ spec/backends/yaml_archive_spec.rb
23
+ spec/fixtures/blogger_authenticate_response.yml
24
+ spec/fixtures/twitter_response.yml
25
+ spec/spec.opts
26
+ spec/spec_helper.rb
27
+ spec/twitter_archive_spec.rb
28
+ tasks/rspec.rake
29
+ twitter_archive.gemspec
data/README.rdoc ADDED
@@ -0,0 +1,91 @@
1
+ = twitter_archive
2
+
3
+ * http://github.com/csexton/twitter_archive
4
+
5
+ == DESCRIPTION:
6
+
7
+ An archiving utility for Twitter.
8
+
9
+ I use my blog as a way to chronicle the things in my life, and I noticed with the introduction of Twitter into my normal routine I found that I was not blogging as much. What I wanted to be able to do is incorporate the twitters into my blog timeline. And while I was able to do some JavaScript trickery to display the twitters on my blog, they were not *in* the blog. Now if I ever want to go back and look up exactly what day my son got his second tooth, I can do so by digging through the blog archives.
10
+
11
+ twitter_archive supports multiple backends. I use Blogger, so I have support for that, as well as a very simple yaml archive backend that was intended for testing, but would provide a pretty good (and easy to parse) plan text backup of Twitter.
12
+
13
+
14
+ == FEATURES/PROBLEMS:
15
+
16
+ Archive your Twitter messages.
17
+
18
+ == SYNOPSIS:
19
+
20
+ === YAML ARCHIVE BACKEND:
21
+
22
+ This requires a config file placed in the user's home directory:
23
+
24
+ Example ~/twitter_archive.yml for use with the yaml archive backend:
25
+
26
+ accounts:
27
+ - name: fuzzymonk
28
+ - name: amperecat
29
+ - name: jnunemaker
30
+ yaml_file: /home/your-user-name/twitter_archive/posts.yml
31
+
32
+ You can enter mutiple twitter accounts, and it will simply interate through them. You should know that twitter_archive will make seperate requests for each account, so unles you have been {IP whitelisted}[http://twitter.com/help/request_whitelisting] by Twitter you can hit their rate limits pretty easily.
33
+
34
+ === BLOGGER ARCHIVE BACKEND:
35
+
36
+ This requires a config file placed in the user's home directory:
37
+
38
+ Example ~/twitter_archive.yml for use with the Blogger archive backend:
39
+
40
+ accounts:
41
+ - name: fuzzymonk
42
+ blogger_user: blogger-user # Normally your gmail address
43
+ blogger_pass: blogger-password
44
+ blogger_title: Twitter # The title you want for you blog post
45
+ blogger_id: 1234567891234567890 #
46
+ backend: blogger
47
+
48
+ To find your Blogger Blog ID refer to the {Blogger Help Center}[http://help.blogger.com/bin/answer.py?hl=en&answer=42191]
49
+
50
+ twitter_archive was intended to be run as a cron job, prolly once a day. It will post in a digest format, collecting all the twitters into one blog post.
51
+
52
+ == INSTALL:
53
+
54
+ Get the gem:
55
+
56
+ sudo gem install twitter_archive
57
+
58
+ Edit crontab to add twitter_archive:
59
+
60
+ $ crontab -e
61
+
62
+ Then Add a line like the following:
63
+
64
+ 0 0 * * * twitter_archive > /home/your-user-name/logs/twitter_archive.log
65
+
66
+ This will run everyday at midnight. You can leave off the "> /home/.../twitter_archive.log" if you don't want to keep logs.
67
+
68
+ == LICENSE:
69
+
70
+ (The MIT License)
71
+
72
+ Copyright (c) 2009 Christopher Sexton
73
+
74
+ Permission is hereby granted, free of charge, to any person obtaining
75
+ a copy of this software and associated documentation files (the
76
+ 'Software'), to deal in the Software without restriction, including
77
+ without limitation the rights to use, copy, modify, merge, publish,
78
+ distribute, sublicense, and/or sell copies of the Software, and to
79
+ permit persons to whom the Software is furnished to do so, subject to
80
+ the following conditions:
81
+
82
+ The above copyright notice and this permission notice shall be
83
+ included in all copies or substantial portions of the Software.
84
+
85
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
86
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
87
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
88
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
89
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
90
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
91
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,30 @@
1
+ ProjectName = 'twitter_archive'
2
+
3
+ require 'rubygems'
4
+ require 'rake'
5
+ require 'echoe'
6
+ require 'spec/rake/spectask'
7
+ require "lib/#{ProjectName}/version"
8
+
9
+ Echoe.new(ProjectName, TwitterArchive::VERSION) do |p|
10
+ p.description = "Twitter archive utility"
11
+ p.url = "http://github.com/csexton/twitter_archive"
12
+ p.author = "Christohper Sexton"
13
+ p.email = "csexton@gmail.com"
14
+ p.extra_deps = [['twitter', '>= 0.4'], ['hpricot', '>= 0.6']]
15
+ p.need_tar_gz = false
16
+ p.docs_host = "http://github.com/csexton/twitter_archive/wikis"
17
+ end
18
+
19
+ desc 'Preps the gem for a new release'
20
+ task :prepare do
21
+ %w[manifest build_gemspec].each do |task|
22
+ Rake::Task[task].invoke
23
+ end
24
+ end
25
+
26
+ Dir['tasks/**/*.rake'].each { |t| load t }
27
+
28
+ Rake::Task[:default].prerequisites.clear
29
+ task :default => :spec
30
+
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require "#{File.dirname(__FILE__)}/../lib/twitter_archive"
3
+
4
+ TwitterArchive::Runner::runner
data/config/test.yml ADDED
@@ -0,0 +1,5 @@
1
+ ---
2
+ accounts:
3
+ - name: fuzzymonk
4
+ - name: jnunemaker
5
+ backend: yaml
@@ -0,0 +1,31 @@
1
+ This was taken from GDataRuby Gem by Dion Almaer.
2
+
3
+ Mostly because it was not current on rubyforge, and I could get more recent source on github.
4
+
5
+ http://gdata-ruby.rubyforge.net
6
+
7
+ LICENSE
8
+
9
+ (The MIT License)
10
+
11
+ Copyright (c) 2007 FIX
12
+
13
+ Permission is hereby granted, free of charge, to any person obtaining
14
+ a copy of this software and associated documentation files (the
15
+ 'Software'), to deal in the Software without restriction, including
16
+ without limitation the rights to use, copy, modify, merge, publish,
17
+ distribute, sublicense, and/or sell copies of the Software, and to
18
+ permit persons to whom the Software is furnished to do so, subject to
19
+ the following conditions:
20
+
21
+ The above copyright notice and this permission notice shall be
22
+ included in all copies or substantial portions of the Software.
23
+
24
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
25
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
27
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
28
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
29
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
30
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31
+
@@ -0,0 +1,76 @@
1
+ require 'net/http'
2
+ require 'net/https'
3
+ require 'uri'
4
+ require 'rubygems'
5
+ require 'hpricot'
6
+
7
+ #
8
+ # Make it east to use some of the convenience methods using https
9
+ #
10
+ module Net
11
+ class HTTPS < HTTP
12
+ def initialize(address, port = nil)
13
+ super(address, port)
14
+ self.use_ssl = true
15
+ end
16
+ end
17
+ end
18
+
19
+ module GData
20
+ GOOGLE_LOGIN_URL = URI.parse('https://www.google.com/accounts/ClientLogin')
21
+
22
+ class Base
23
+
24
+ attr_reader :service, :source, :url
25
+
26
+ def initialize(service, source, url)
27
+ @service = service
28
+ @source = source
29
+ @url = url
30
+ end
31
+
32
+ def authenticate(email, password)
33
+ $VERBOSE = nil
34
+ response = Net::HTTPS.post_form(GOOGLE_LOGIN_URL,
35
+ {'Email' => email,
36
+ 'Passwd' => password,
37
+ 'source' => source,
38
+ 'service' => service })
39
+
40
+ response.error! unless response.kind_of? Net::HTTPSuccess
41
+
42
+ @headers = {
43
+ 'Authorization' => "GoogleLogin auth=#{response.body.split(/=/).last}",
44
+ 'GData-Version' => '2',
45
+ 'Content-Type' => 'application/atom+xml'
46
+ }
47
+ end
48
+
49
+ def request(path)
50
+ response, data = get(path)
51
+ data
52
+ end
53
+
54
+ def get(path)
55
+ response, data = http.get(path, @headers)
56
+ end
57
+
58
+ def post(path, entry)
59
+ http.post(path, entry, @headers)
60
+ end
61
+
62
+ def put(path, entry)
63
+ h = @headers
64
+ h['X-HTTP-Method-Override'] = 'PUT' # just to be nice, add the method override
65
+
66
+ http.put(path, entry, h)
67
+ end
68
+
69
+ def http
70
+ conn = Net::HTTP.new(url, 80)
71
+ #conn.set_debug_output $stderr
72
+ conn
73
+ end
74
+
75
+ end
76
+ end
@@ -0,0 +1,72 @@
1
+ require File.dirname(__FILE__) + '/base'
2
+ require 'builder'
3
+
4
+ module GData
5
+
6
+ class Blogger < GData::Base
7
+
8
+ def initialize(blog_id, entry_id=nil)
9
+ @blog_id = blog_id
10
+ @entry_id = entry_id
11
+ super 'blogger', 'gdata-ruby', 'www.blogger.com'
12
+ end
13
+
14
+ def feed
15
+ request "/feeds/#{@blog_id}/posts/default"
16
+ end
17
+
18
+ def list_blogs(profile_id)
19
+ request "/feeds/#{profile_id}/blogs"
20
+ end
21
+
22
+ def entry
23
+ @entry ||= Hpricot(request("/feeds/#{@blog_id}/posts/default/#{@entry_id}"))
24
+ end
25
+
26
+ def enclosure
27
+ entry.search('//link[@rel="enclosure"]')
28
+ end
29
+
30
+ def enclosure?
31
+ enclosure.any?
32
+ end
33
+
34
+ def add_enclosure(enclosure_url, enclosure_length)
35
+ raise "An enclosure has already been added to this entry" if enclosure?
36
+ # todo(stevejenson): replace with builder
37
+ entry.search('//entry').append(%Q{<link rel="enclosure" type="audio/mpeg" title="MP3" href="#{enclosure_url}" length="#{enclosure_length}" />})
38
+ save_entry
39
+ end
40
+
41
+ def remove_enclosure
42
+ if enclosure?
43
+ enclosure.remove
44
+ save_entry
45
+ end
46
+ end
47
+
48
+ def save_entry
49
+ path = "/feeds/#{@blog_id}/posts/default/#{@entry_id}"
50
+
51
+ put(path, entry.to_s)
52
+ end
53
+
54
+ # Creates a new entry with the given title and body
55
+ def entry(title, body)
56
+ x = Builder::XmlMarkup.new :indent => 2
57
+ @entry = x.entry 'xmlns' => 'http://www.w3.org/2005/Atom' do
58
+ x.title title, 'type' => 'text'
59
+ x.content 'type' => 'xhtml' do
60
+ x.div 'xmlns' => 'http://www.w3.org/1999/xhtml' do
61
+ x << body
62
+ end
63
+ end
64
+ end
65
+
66
+ path = "/feeds/#{@blog_id}/posts/default"
67
+ post(path, @entry)
68
+ end
69
+
70
+ end
71
+
72
+ end
@@ -0,0 +1,32 @@
1
+ <%
2
+ # time format
3
+ %>
4
+ <table class="twitter">
5
+ <tbody class="twitter">
6
+ <% results.each do |result| %>
7
+ <tr class="twitter-status u-<%= result['from_user'] %>">
8
+ <td class="">
9
+ <a href="http://twitter.com/<%= result['from_user'] %>" class="url">
10
+ <img alt="Tom Dougherty" class="twitter-avatar" height="48" src="<%= result['profile_image_url'] %>" width="48" />
11
+ </a>
12
+ </td>
13
+ <td class="twitter-body">
14
+ <div>
15
+ <strong>
16
+ <a href="http://twitter.com/<%= result['from_user'] %>" class="twitter-user" title="<%= result['from_user'] %>">
17
+ <%= result['from_user'] %>
18
+ </a>
19
+ </strong>
20
+ <span class="twitter-text">
21
+ <%= result['text'] %>
22
+ </span>
23
+ <span class="twitter-date" style="font-style: italic; font-size:smaller;">
24
+ <%= format_time(result['created_at']) %>
25
+ </span>
26
+ </div>
27
+ </td>
28
+ </tr>
29
+ <% end %>
30
+ </tbody>
31
+
32
+ </table>
@@ -0,0 +1,31 @@
1
+ require 'erb'
2
+ require File.dirname(__FILE__) + '/blogger/blogger'
3
+
4
+ module TwitterArchive
5
+ module Backends
6
+ class BloggerArchive
7
+ def archive(twitter_results, opts=nil)
8
+ if twitter_results.length > 0
9
+ blogger = GData::Blogger.new(opts['blogger_id'])
10
+ blogger.authenticate(opts['blogger_user'], opts['blogger_pass'])
11
+ blogger.entry(opts['blogger_title'] || 'Twitter', format_post(twitter_results))
12
+ "Posting to blogger id #{opts['blogger_id']}, user #{opts['blogger_user']}"
13
+ else
14
+ "Nothing to post to blogger"
15
+ end
16
+ end
17
+
18
+ def format_post(results)
19
+ results
20
+ template = ERB.new(File.open(File.dirname(__FILE__) + '/blogger/post_body.html.erb') {|f| f.read})
21
+ template.result(binding)
22
+ end
23
+
24
+ def format_time (date_str)
25
+ time = Time.gm(*ParseDate.parsedate(date_str)[0..4])
26
+ time.strftime("%m/%d/%Y at %I:%M%p")
27
+ end
28
+ end
29
+ end
30
+ end
31
+
@@ -0,0 +1,9 @@
1
+ module TwitterArchive
2
+ module Backends
3
+ class YamlArchive
4
+ def archive(results, opts=nil)
5
+ results.to_yaml
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,53 @@
1
+ require 'parsedate'
2
+ Dir.glob(File.dirname(__FILE__)+ '/backends/*.rb').each {|f| require f }
3
+
4
+ module TwitterArchive
5
+
6
+ class Base
7
+ attr_accessor :config_file, :config
8
+
9
+ def initialize(config_file = nil)
10
+ @config_file = config_file || ENV['HOME'] + '/.twitter_archive.yml'
11
+ end
12
+
13
+ def get_latest
14
+ all_results = []
15
+ last_max_id = 0
16
+ @config['accounts'].each do |account|
17
+ twitter_response = fetch_from_account(account['name'], config['last_max_id'] || 0)
18
+ config['current_twitter_account'] = account['name']
19
+ puts "Collected #{twitter_response['results'].length} tweets from #{account['name']}"
20
+
21
+ all_results = all_results + twitter_response['results']
22
+ last_max_id = twitter_response['max_id']
23
+ end
24
+
25
+ config['last_max_id'] = last_max_id
26
+
27
+ all_results.sort! {|a, b| b['created_at'] <=> a['created_at'] }
28
+
29
+ backend = load_backend(config['backend'])
30
+
31
+ backend.archive(all_results, config)
32
+ end
33
+
34
+ def fetch_from_account(name, last_max_id=0)
35
+ Twitter::Search.new.from(name).since(last_max_id).fetch
36
+ end
37
+
38
+ def load_config
39
+ @config = YAML::load_file(@config_file)
40
+ end
41
+
42
+ def save_config
43
+ File.open(@config_file, 'w') do |out|
44
+ YAML.dump(config, out)
45
+ end
46
+ end
47
+
48
+ def load_backend(backend_name)
49
+ eval "TwitterArchive::Backends::#{backend_name.capitalize}Archive.new"
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,12 @@
1
+ module TwitterArchive
2
+ class Runner
3
+ def self.runner
4
+ puts "Running Twitter Archiver"
5
+
6
+ ta = TwitterArchive::Base.new
7
+ ta.load_config
8
+ puts ta.get_latest
9
+ ta.save_config
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,3 @@
1
+ module TwitterArchive
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,13 @@
1
+ #$:.unshift(File.dirname(__FILE__)) unless
2
+ # $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ require 'yaml'
5
+ require 'rubygems'
6
+ require 'twitter'
7
+
8
+ $:.unshift(File.dirname(__FILE__))
9
+ require 'twitter_archive/base'
10
+ require 'twitter_archive/runner'
11
+ require 'twitter_archive/version'
12
+
13
+ module TwitterArchive; end
data/script/console ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # File: script/console
3
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
4
+
5
+ libs = " -r irb/completion"
6
+ # Perhaps use a console_lib to store any extra methods I may want available in the cosole
7
+ # libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
8
+ libs << " -r #{File.dirname(__FILE__) + '/../lib/twitter_archive.rb'}"
9
+ puts "Loading twitter_archive gem"
10
+ exec "#{irb} #{libs} --simple-prompt"
data/script/destroy ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/destroy'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Destroy.new.run(ARGV)
data/script/generate ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/generate'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Generate.new.run(ARGV)
@@ -0,0 +1,42 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+ require File.dirname(__FILE__) + '/../../lib/twitter_archive/backends/blogger_archive.rb'
3
+
4
+ describe TwitterArchive::Backends::BloggerArchive do
5
+ before(:all) do
6
+ puts " WARNING Not testing with live blogger, set TEST_BLOGGER to enable" unless ENV['TEST_BLOGGER']
7
+ end
8
+
9
+ before(:each) do
10
+ @ba = TwitterArchive::Backends::BloggerArchive.new
11
+ @config = YAML::load_file(ENV['HOME'] + '/.twitter_archive.yml')
12
+ @twitter_response = YAML::load_file File.dirname(__FILE__) +'/../fixtures/twitter_response.yml'
13
+
14
+ if(ENV['TEST_BLOGGER'])
15
+ Net::HTTPS.stub!(:post_form).and_return(YAML::load_file(
16
+ File.dirname(__FILE__) + '/../../fixtures/blogger_authenticate_response.yml'))
17
+ GData
18
+ end
19
+
20
+ end
21
+
22
+ it "should create an instance" do
23
+ @ba.should be_an_instance_of(TwitterArchive::Backends::BloggerArchive)
24
+ end
25
+
26
+ it "should test post to blogger" do
27
+ @config['blogger_title'] = "Testing twitter_archive"
28
+ @ba.archive(@twitter_response['results'], @config)
29
+ end
30
+
31
+ it "should format html from the tweets" do
32
+ body = @ba.format_post(@twitter_response['results'])
33
+
34
+ body.should_not be_nil
35
+ end
36
+
37
+ it "should format time like google" do
38
+ @ba.format_time("Sun, 28 Dec 2008 23:38:46 +0000").should eql "12/28/2008 at 11:38PM"
39
+ end
40
+
41
+
42
+ end
@@ -0,0 +1,13 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+ require File.dirname(__FILE__) + '/../../lib/twitter_archive/backends/yaml_archive.rb'
3
+
4
+ describe TwitterArchive::Backends::YamlArchive do
5
+ before(:each) do
6
+ @ya = TwitterArchive::Backends::YamlArchive.new
7
+ end
8
+
9
+ it "should create an instance" do
10
+ @ya.should be_an_instance_of(TwitterArchive::Backends::YamlArchive)
11
+ end
12
+
13
+ end
@@ -0,0 +1,30 @@
1
+ --- !ruby/object:Net::HTTPOK
2
+ body: |
3
+ SID=DQAAAH4AAAAK5SScZgxeJS9BP03rjNP0EeUm0X8jvFKb6vXpRBMG-4aIkON6mbjjlqvpip7vxS8H_9_bNonFN-6PDEw8-xuTtszBogb7qRe4-gzhMc7dDX65VHEw-QmCmyYr5gGvWUP5x_5E0zh-XWef-viVNvbnCx7agwI-CCvBwAzl7fQQVw
4
+ LSID=DQAAAIAAAACZDlUEEuBRdQt9oEgJI2rjL9PJUNLnoDPTQA0duvmtRf3cxhh5DDcPXpfGI6tF-2K7-8ZHubK_4FiShCGhoKTE6d4vzTs0SWz5Itk8MpF_qZoye7AwCb3YVG4tgjALpI0RNl8SEuWTg2Jtiqn2So2mlxzivHeOv8rAE-s01p1qHA
5
+ Auth=DQAAAH8AAACZDlUEEuBRdQt9oEgJI2rjL9PJUNLnoDPTQA0duvmtRf3cxhh5DDcPXpfGI6tF-2J0oYw6koUPpBpn3QOJoJ3ps7lCYCqwPeCc64e265o4UyYgEYFivgbDrI7akWGSkmVvO2hFw6NGxZyGx6-MrKSKFph4MgORs57vPRnrj2UjJw
6
+
7
+ body_exist: true
8
+ code: "200"
9
+ header:
10
+ cache-control:
11
+ - no-cache, no-store
12
+ x-content-type-options:
13
+ - nosniff
14
+ expires:
15
+ - Mon, 01-Jan-1990 00:00:00 GMT
16
+ date:
17
+ - Wed, 31 Dec 2008 20:50:14 GMT
18
+ content-type:
19
+ - text/plain
20
+ server:
21
+ - GFE/1.3
22
+ content-length:
23
+ - "563"
24
+ pragma:
25
+ - no-cache
26
+ http_version: "1.1"
27
+ message: OK
28
+ read: true
29
+ socket:
30
+
@@ -0,0 +1,132 @@
1
+ ---
2
+ max_id: 1083275701
3
+ since_id: 0
4
+ results:
5
+ - text: "@beejpowers glad it was working for you!"
6
+ from_user: fuzzymonk
7
+ to_user: beejpowers
8
+ to_user_id: 2203390
9
+ id: 1083002747
10
+ iso_language_code: en
11
+ from_user_id: 44397
12
+ created_at: Sun, 28 Dec 2008 23:38:46 +0000
13
+ profile_image_url: http://s3.amazonaws.com/twitter_production/profile_images/30300852/TaylorandMcLauren-jabber_normal.jpg
14
+ - text: Testing my twitter app.
15
+ from_user: fuzzymonk
16
+ to_user_id:
17
+ id: 1082726875
18
+ iso_language_code: en
19
+ from_user_id: 44397
20
+ created_at: Sun, 28 Dec 2008 20:14:53 +0000
21
+ profile_image_url: http://s3.amazonaws.com/twitter_production/profile_images/30300852/TaylorandMcLauren-jabber_normal.jpg
22
+ - text: Chicken nugget picnic FTW!
23
+ from_user: fuzzymonk
24
+ to_user_id:
25
+ id: 1082568072
26
+ iso_language_code: de
27
+ from_user_id: 44397
28
+ created_at: Sun, 28 Dec 2008 18:12:25 +0000
29
+ profile_image_url: http://s3.amazonaws.com/twitter_production/profile_images/30300852/TaylorandMcLauren-jabber_normal.jpg
30
+ - text: Riding trikes.
31
+ from_user: fuzzymonk
32
+ to_user_id:
33
+ id: 1082523321
34
+ iso_language_code: nl
35
+ from_user_id: 44397
36
+ created_at: Sun, 28 Dec 2008 17:36:59 +0000
37
+ profile_image_url: http://s3.amazonaws.com/twitter_production/profile_images/30300852/TaylorandMcLauren-jabber_normal.jpg
38
+ - text: Nursery duty. 9:5 helper to toddler ratio. Why did we wake up so early?
39
+ from_user: fuzzymonk
40
+ to_user_id:
41
+ id: 1082306470
42
+ iso_language_code: en
43
+ from_user_id: 44397
44
+ created_at: Sun, 28 Dec 2008 14:24:12 +0000
45
+ profile_image_url: http://s3.amazonaws.com/twitter_production/profile_images/30300852/TaylorandMcLauren-jabber_normal.jpg
46
+ - text: "@beejpowers I need to go back to work to recover from the holiday."
47
+ from_user: fuzzymonk
48
+ to_user: beejpowers
49
+ to_user_id: 2203390
50
+ id: 1081719755
51
+ iso_language_code: en
52
+ from_user_id: 44397
53
+ created_at: Sun, 28 Dec 2008 03:00:30 +0000
54
+ profile_image_url: http://s3.amazonaws.com/twitter_production/profile_images/30300852/TaylorandMcLauren-jabber_normal.jpg
55
+ - text: Where can I get one? http://tinyurl.com/7dxzrv
56
+ from_user: fuzzymonk
57
+ to_user_id:
58
+ id: 1081473926
59
+ iso_language_code: en
60
+ from_user_id: 44397
61
+ created_at: Sat, 27 Dec 2008 23:35:21 +0000
62
+ profile_image_url: http://s3.amazonaws.com/twitter_production/profile_images/30300852/TaylorandMcLauren-jabber_normal.jpg
63
+ - text: Don't like pandemonium. Go away
64
+ from_user: fuzzymonk
65
+ to_user_id:
66
+ id: 1081233677
67
+ iso_language_code: en
68
+ from_user_id: 44397
69
+ created_at: Sat, 27 Dec 2008 20:08:54 +0000
70
+ profile_image_url: http://s3.amazonaws.com/twitter_production/profile_images/30300852/TaylorandMcLauren-jabber_normal.jpg
71
+ - text: "[dotfiles] http://is.gd/dBpg Christopher Sexton - Removing the os specific scripts"
72
+ from_user: fuzzymonk
73
+ to_user_id:
74
+ id: 1079851223
75
+ iso_language_code: en
76
+ from_user_id: 44397
77
+ created_at: Fri, 26 Dec 2008 21:18:11 +0000
78
+ profile_image_url: http://s3.amazonaws.com/twitter_production/profile_images/30300852/TaylorandMcLauren-jabber_normal.jpg
79
+ - text: "[dotfiles] http://is.gd/dBpf Christopher Sexton - Auto linking files in home/"
80
+ from_user: fuzzymonk
81
+ to_user_id:
82
+ id: 1079851212
83
+ iso_language_code: en
84
+ from_user_id: 44397
85
+ created_at: Fri, 26 Dec 2008 21:18:10 +0000
86
+ profile_image_url: http://s3.amazonaws.com/twitter_production/profile_images/30300852/TaylorandMcLauren-jabber_normal.jpg
87
+ - text: "[dotfiles] http://is.gd/dBph Christopher Sexton - Added colors and fixed link if"
88
+ from_user: fuzzymonk
89
+ to_user_id:
90
+ id: 1079851233
91
+ iso_language_code: en
92
+ from_user_id: 44397
93
+ created_at: Fri, 26 Dec 2008 21:18:09 +0000
94
+ profile_image_url: http://s3.amazonaws.com/twitter_production/profile_images/30300852/TaylorandMcLauren-jabber_normal.jpg
95
+ - text: "[dotfiles] http://is.gd/dAcc Christopher Sexton - Added check if the file exists before trying to rename it."
96
+ from_user: fuzzymonk
97
+ to_user_id:
98
+ id: 1079644342
99
+ iso_language_code: en
100
+ from_user_id: 44397
101
+ created_at: Fri, 26 Dec 2008 18:31:37 +0000
102
+ profile_image_url: http://s3.amazonaws.com/twitter_production/profile_images/30300852/TaylorandMcLauren-jabber_normal.jpg
103
+ - text: "'Nene' is a derivative of 'Neal'"
104
+ from_user: fuzzymonk
105
+ to_user_id:
106
+ id: 1079585237
107
+ iso_language_code: it
108
+ from_user_id: 44397
109
+ created_at: Fri, 26 Dec 2008 17:45:34 +0000
110
+ profile_image_url: http://s3.amazonaws.com/twitter_production/profile_images/30300852/TaylorandMcLauren-jabber_normal.jpg
111
+ - text: "[cookbook] http://is.gd/dzKL Christopher Sexton - Fixed link_to in application"
112
+ from_user: fuzzymonk
113
+ to_user_id:
114
+ id: 1079579679
115
+ iso_language_code: en
116
+ from_user_id: 44397
117
+ created_at: Fri, 26 Dec 2008 17:41:05 +0000
118
+ profile_image_url: http://s3.amazonaws.com/twitter_production/profile_images/30300852/TaylorandMcLauren-jabber_normal.jpg
119
+ - text: "[cookbook] http://is.gd/dzKJ Christopher Sexton - Freezing to rails 2.1.1"
120
+ from_user: fuzzymonk
121
+ to_user_id:
122
+ id: 1079579667
123
+ iso_language_code: en
124
+ from_user_id: 44397
125
+ created_at: Fri, 26 Dec 2008 17:41:03 +0000
126
+ profile_image_url: http://s3.amazonaws.com/twitter_production/profile_images/30300852/TaylorandMcLauren-jabber_normal.jpg
127
+ results_per_page: 15
128
+ refresh_url: ?since_id=1083275701&q=from%3Afuzzymonk
129
+ next_page: ?page=2&max_id=1083275701&q=from%3Afuzzymonk
130
+ completed_in: 0.01725
131
+ query: from%3Afuzzymonk
132
+ page: 1
data/spec/spec.opts ADDED
@@ -0,0 +1,4 @@
1
+ --colour
2
+ --format specdoc
3
+ --loadby mtime
4
+ --reverse
@@ -0,0 +1,10 @@
1
+ begin
2
+ require 'spec'
3
+ rescue LoadError
4
+ require 'rubygems'
5
+ gem 'rspec'
6
+ require 'spec'
7
+ end
8
+
9
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
10
+ require 'twitter_archive'
@@ -0,0 +1,53 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ describe TwitterArchive::Base do
4
+ before(:each) do
5
+ @ta = TwitterArchive::Base.new
6
+ @ta.stub!(:fetch_from_account).and_return(YAML::load_file(
7
+ File.dirname(__FILE__) + '/fixtures/twitter_response.yml'))
8
+ @ta.stub!(:save_config).and_return(true)
9
+ @ta.config_file = File.dirname(__FILE__) + '/../config/test.yml'
10
+ # TODO stubb out backend
11
+ end
12
+
13
+ it "should create an instance" do
14
+ @ta.should be_an_instance_of(TwitterArchive::Base)
15
+ end
16
+
17
+ it "should load the yaml file" do
18
+ @ta.load_config
19
+ @ta.config['backend'].should eql('yaml')
20
+ @ta.config['accounts'][0]['name'].should eql('fuzzymonk')
21
+ end
22
+
23
+ it "should stub the fetch method" do
24
+ @ta.fetch_from_account['max_id'].should eql(1083275701)
25
+ end
26
+
27
+ it "should stub the save_config" do
28
+ @ta.load_config
29
+ @ta.config['joe'] = "test"
30
+ @ta.save_config
31
+
32
+ @ta.load_config
33
+ @ta.config['joe'].should be_nil
34
+ end
35
+
36
+ it "should update the last_max_id in the config file" do
37
+ @ta.load_config
38
+ @ta.get_latest
39
+ @ta.config['last_max_id'].should_not eql(@ta.load_config['last_max_id'])
40
+ end
41
+
42
+ it "should load the yaml backend dynamically" do
43
+ @ta.load_backend('yaml').should be_an_instance_of TwitterArchive::Backends::YamlArchive
44
+ end
45
+
46
+ it "should raise an error when loading an invalid backend" do
47
+ lambda do
48
+ @ta.load_backend('poopie')
49
+ @processor.process(StringIO.new("z"*31))
50
+ end.should raise_error(NameError)
51
+
52
+ end
53
+ end
data/tasks/rspec.rake ADDED
@@ -0,0 +1,21 @@
1
+ begin
2
+ require 'spec'
3
+ rescue LoadError
4
+ require 'rubygems'
5
+ require 'spec'
6
+ end
7
+ begin
8
+ require 'spec/rake/spectask'
9
+ rescue LoadError
10
+ puts <<-EOS
11
+ To use rspec for testing you must install rspec gem:
12
+ gem install rspec
13
+ EOS
14
+ exit(0)
15
+ end
16
+
17
+ desc "Run the specs under spec/models"
18
+ Spec::Rake::SpecTask.new do |t|
19
+ t.spec_opts = ['--options', "spec/spec.opts"]
20
+ t.spec_files = FileList['spec/**/*_spec.rb']
21
+ end
@@ -0,0 +1,42 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{twitter_archive}
5
+ s.version = "0.0.1"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Christohper Sexton"]
9
+ s.date = %q{2009-01-02}
10
+ s.default_executable = %q{twitter_archive}
11
+ s.description = %q{Twitter archive utility}
12
+ s.email = %q{csexton@gmail.com}
13
+ s.executables = ["twitter_archive"]
14
+ s.extra_rdoc_files = ["bin/twitter_archive", "lib/twitter_archive/backends/blogger/base.rb", "lib/twitter_archive/backends/blogger/blogger.rb", "lib/twitter_archive/backends/blogger/post_body.html.erb", "lib/twitter_archive/backends/blogger/README", "lib/twitter_archive/backends/blogger_archive.rb", "lib/twitter_archive/backends/yaml_archive.rb", "lib/twitter_archive/base.rb", "lib/twitter_archive/runner.rb", "lib/twitter_archive/version.rb", "lib/twitter_archive.rb", "LICENSE", "README.rdoc", "tasks/rspec.rake"]
15
+ s.files = ["bin/twitter_archive", "config/test.yml", "History", "lib/twitter_archive/backends/blogger/base.rb", "lib/twitter_archive/backends/blogger/blogger.rb", "lib/twitter_archive/backends/blogger/post_body.html.erb", "lib/twitter_archive/backends/blogger/README", "lib/twitter_archive/backends/blogger_archive.rb", "lib/twitter_archive/backends/yaml_archive.rb", "lib/twitter_archive/base.rb", "lib/twitter_archive/runner.rb", "lib/twitter_archive/version.rb", "lib/twitter_archive.rb", "LICENSE", "Manifest", "Rakefile", "README.rdoc", "script/console", "script/destroy", "script/generate", "spec/backends/blogger_archive_spec.rb", "spec/backends/yaml_archive_spec.rb", "spec/fixtures/blogger_authenticate_response.yml", "spec/fixtures/twitter_response.yml", "spec/spec.opts", "spec/spec_helper.rb", "spec/twitter_archive_spec.rb", "tasks/rspec.rake", "twitter_archive.gemspec"]
16
+ s.has_rdoc = true
17
+ s.homepage = %q{http://github.com/csexton/twitter_archive}
18
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Twitter_archive", "--main", "README.rdoc"]
19
+ s.require_paths = ["lib"]
20
+ s.rubyforge_project = %q{twitter_archive}
21
+ s.rubygems_version = %q{1.3.1}
22
+ s.summary = %q{Twitter archive utility}
23
+
24
+ if s.respond_to? :specification_version then
25
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
26
+ s.specification_version = 2
27
+
28
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
29
+ s.add_runtime_dependency(%q<twitter>, [">= 0.4"])
30
+ s.add_runtime_dependency(%q<hpricot>, [">= 0.6"])
31
+ s.add_development_dependency(%q<echoe>, [">= 0"])
32
+ else
33
+ s.add_dependency(%q<twitter>, [">= 0.4"])
34
+ s.add_dependency(%q<hpricot>, [">= 0.6"])
35
+ s.add_dependency(%q<echoe>, [">= 0"])
36
+ end
37
+ else
38
+ s.add_dependency(%q<twitter>, [">= 0.4"])
39
+ s.add_dependency(%q<hpricot>, [">= 0.6"])
40
+ s.add_dependency(%q<echoe>, [">= 0"])
41
+ end
42
+ end
metadata ADDED
@@ -0,0 +1,125 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: csexton-twitter_archive
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Christohper Sexton
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-01-02 00:00:00 -08:00
13
+ default_executable: twitter_archive
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: twitter
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: "0.4"
23
+ version:
24
+ - !ruby/object:Gem::Dependency
25
+ name: hpricot
26
+ version_requirement:
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - - ">="
30
+ - !ruby/object:Gem::Version
31
+ version: "0.6"
32
+ version:
33
+ - !ruby/object:Gem::Dependency
34
+ name: echoe
35
+ version_requirement:
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: "0"
41
+ version:
42
+ description: Twitter archive utility
43
+ email: csexton@gmail.com
44
+ executables:
45
+ - twitter_archive
46
+ extensions: []
47
+
48
+ extra_rdoc_files:
49
+ - bin/twitter_archive
50
+ - lib/twitter_archive/backends/blogger/base.rb
51
+ - lib/twitter_archive/backends/blogger/blogger.rb
52
+ - lib/twitter_archive/backends/blogger/post_body.html.erb
53
+ - lib/twitter_archive/backends/blogger/README
54
+ - lib/twitter_archive/backends/blogger_archive.rb
55
+ - lib/twitter_archive/backends/yaml_archive.rb
56
+ - lib/twitter_archive/base.rb
57
+ - lib/twitter_archive/runner.rb
58
+ - lib/twitter_archive/version.rb
59
+ - lib/twitter_archive.rb
60
+ - LICENSE
61
+ - README.rdoc
62
+ - tasks/rspec.rake
63
+ files:
64
+ - bin/twitter_archive
65
+ - config/test.yml
66
+ - History
67
+ - lib/twitter_archive/backends/blogger/base.rb
68
+ - lib/twitter_archive/backends/blogger/blogger.rb
69
+ - lib/twitter_archive/backends/blogger/post_body.html.erb
70
+ - lib/twitter_archive/backends/blogger/README
71
+ - lib/twitter_archive/backends/blogger_archive.rb
72
+ - lib/twitter_archive/backends/yaml_archive.rb
73
+ - lib/twitter_archive/base.rb
74
+ - lib/twitter_archive/runner.rb
75
+ - lib/twitter_archive/version.rb
76
+ - lib/twitter_archive.rb
77
+ - LICENSE
78
+ - Manifest
79
+ - Rakefile
80
+ - README.rdoc
81
+ - script/console
82
+ - script/destroy
83
+ - script/generate
84
+ - spec/backends/blogger_archive_spec.rb
85
+ - spec/backends/yaml_archive_spec.rb
86
+ - spec/fixtures/blogger_authenticate_response.yml
87
+ - spec/fixtures/twitter_response.yml
88
+ - spec/spec.opts
89
+ - spec/spec_helper.rb
90
+ - spec/twitter_archive_spec.rb
91
+ - tasks/rspec.rake
92
+ - twitter_archive.gemspec
93
+ has_rdoc: true
94
+ homepage: http://github.com/csexton/twitter_archive
95
+ post_install_message:
96
+ rdoc_options:
97
+ - --line-numbers
98
+ - --inline-source
99
+ - --title
100
+ - Twitter_archive
101
+ - --main
102
+ - README.rdoc
103
+ require_paths:
104
+ - lib
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: "0"
110
+ version:
111
+ required_rubygems_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: "1.2"
116
+ version:
117
+ requirements: []
118
+
119
+ rubyforge_project: twitter_archive
120
+ rubygems_version: 1.2.0
121
+ signing_key:
122
+ specification_version: 2
123
+ summary: Twitter archive utility
124
+ test_files: []
125
+