usaidwat 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/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in usaidwat.gemspec
4
+ gemspec
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/usaidwat ADDED
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'usaidwat'
4
+
5
+
6
+ def die(code=1)
7
+ $stderr.puts "Usage: #{File.basename $0} <user> [<subreddit>]"
8
+ exit code
9
+ end
10
+
11
+ die if $*.length < 1 or $*.length > 2
12
+
13
+ subreddit = $*.length == 2 ? $*.last : nil
14
+ reddit_user = USaidWat::RedditUser.new $*.first
15
+ unless subreddit
16
+ comments = reddit_user.retrieve_comments
17
+ exit 2 unless comments
18
+ max_key = 1
19
+ puts reddit_user.username
20
+ puts '-' * reddit_user.username.length
21
+ comments.each { |c| max_key = c.first.length if c.first.length > max_key }
22
+ comments.each { |c| printf "%-*s %s\n", max_key, c.first, c.last }
23
+ else
24
+ comments = reddit_user.comments_for_subreddit subreddit
25
+ is_first = true
26
+ width = `tput cols`.to_i rescue 80
27
+ comments.each do |c|
28
+ puts '-' * width unless is_first
29
+ puts c
30
+ is_first = false
31
+ end
32
+ end
@@ -0,0 +1,150 @@
1
+ require 'fileutils'
2
+ require 'net/http'
3
+ require 'time'
4
+
5
+ require 'rubygems'
6
+ require 'json'
7
+
8
+
9
+ class Hash
10
+ def to_query
11
+ data = self.keys.inject([]) { |parts, key| parts << [URI.encode(key.to_s), URI.encode(self[key].to_s)] }
12
+ data.map{ |t| t.join '=' }.join '&'
13
+ end
14
+ end
15
+
16
+ module USaidWat
17
+ class RedditUser
18
+ COMMENT_COUNT = 100
19
+ COMMENTS_PER_PAGE = 25
20
+
21
+ attr_reader :username
22
+
23
+ def initialize(username)
24
+ @username = username
25
+ self.ensure_cache_dir!
26
+ end
27
+
28
+ def profile_url
29
+ "http://www.reddit.com/user/#{self.username}"
30
+ end
31
+
32
+ def comments_url
33
+ "#{self.profile_url}/comments"
34
+ end
35
+
36
+ def last_update
37
+ return Time.at 0 unless File.exists? self.cache_timestamp_file
38
+ Time.parse File.open(self.cache_timestamp_file).read.chomp
39
+ end
40
+
41
+ def retrieve_comments(options={})
42
+ return self.retrieve_comments_from_cache unless Time.now - self.last_update > 300
43
+ count = options[:count] || COMMENT_COUNT
44
+ cache = options[:cache] || true
45
+ self.destroy_cache!
46
+ comments = self.fetch_comments count
47
+ return nil unless comments
48
+ self.cache_comments comments if cache
49
+ subreddits = Hash.new { |h,k| h[k] = 0 }
50
+ comments.each do |comment|
51
+ subreddit = comment['data']['subreddit'].to_sym
52
+ subreddits[subreddit] += 1
53
+ end
54
+ subreddits.sort { |a,b| b[1] <=> a[1] }
55
+ end
56
+
57
+ def comments_for_subreddit(subreddit)
58
+ self.retrieve_comments
59
+ comments = []
60
+ subreddit_dir = File.join self.comments_dir, subreddit
61
+ Dir.chdir(subreddit_dir) do
62
+ Dir['*'].each do |f|
63
+ path = File.join subreddit_dir, f
64
+ comment = File.open(path).read.chomp
65
+ comments << comment
66
+ end
67
+ end
68
+ comments
69
+ end
70
+
71
+ def retrieve_comments_from_cache
72
+ subreddits = Hash.new { |h,k| h[k] = 0 }
73
+ Dir.chdir(self.comments_dir) do
74
+ Dir['*'].each do |sr|
75
+ next unless File.directory? sr
76
+ Dir["#{sr}/*"].each { |f| subreddits[sr] += 1 }
77
+ end
78
+ end
79
+ subreddits.sort { |a,b| b[1] <=> a[1] }
80
+ end
81
+
82
+ def fetch_comments(count)
83
+ comments = Array.new
84
+ after = nil
85
+ last_page = count / COMMENTS_PER_PAGE
86
+ (1..last_page).each do |i|
87
+ query = i == 1 ? '' : {:count => COMMENTS_PER_PAGE, :after => after}.to_query
88
+ url = "#{self.comments_url}.json?#{query}"
89
+ resp = Net::HTTP.get_response 'www.reddit.com', url
90
+ unless resp.code.to_i == 200
91
+ $stderr.puts "Could not retrieve comments: #{resp.message}"
92
+ return nil
93
+ end
94
+ resp = JSON.parse resp.body
95
+ if resp.key? 'error'
96
+ $stderr.puts "Could not retrieve comments: #{resp['error'] || 'Unknown error'}"
97
+ return nil
98
+ end
99
+ comments += resp['data']['children']
100
+ after = resp['data']['after']
101
+ end
102
+ comments
103
+ end
104
+
105
+ def cache_comments(comments)
106
+ comments.each do |c|
107
+ cid = c['data']['id']
108
+ sr = c['data']['subreddit']
109
+ body = c['data']['body']
110
+ parent_cache_dir = self.subreddit_directory! sr
111
+ cache_file = File.join parent_cache_dir, cid
112
+ File.open(cache_file, 'w') { |f| f.write body }
113
+ end
114
+ File.open(self.cache_timestamp_file, 'w') { |f| f.write Time.now }
115
+ end
116
+
117
+ def cache_dir
118
+ File.join USaidWat::BASE_CACHE_DIR, self.username
119
+ end
120
+
121
+ def cache_timestamp_file
122
+ File.join self.cache_dir, 'updated'
123
+ end
124
+
125
+ def comments_dir
126
+ File.join self.cache_dir, 'comments'
127
+ end
128
+
129
+ def subreddit_directory!(subreddit)
130
+ Dir.mkdir self.comments_dir unless File.exists? self.comments_dir
131
+ cache = File.join self.comments_dir, subreddit
132
+ Dir.mkdir cache unless File.exists? cache
133
+ cache
134
+ end
135
+
136
+ def ensure_cache_dir!
137
+ Dir.mkdir USaidWat::BASE_CACHE_DIR unless File.exists? USaidWat::BASE_CACHE_DIR
138
+ Dir.mkdir self.cache_dir unless File.exists? self.cache_dir
139
+ end
140
+
141
+ def destroy_cache!
142
+ FileUtils.rm_rf self.cache_dir
143
+ self.ensure_cache_dir!
144
+ end
145
+
146
+ def to_s
147
+ "Reddit user: #{self.username}"
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,3 @@
1
+ module USaidWat
2
+ VERSION = "0.0.1"
3
+ end
data/lib/usaidwat.rb ADDED
@@ -0,0 +1,7 @@
1
+ require 'usaidwat/version'
2
+ require 'usaidwat/reddit'
3
+
4
+
5
+ module USaidWat
6
+ BASE_CACHE_DIR = File.join File.expand_path('~'), '.usaidwat'
7
+ end
data/usaidwat.gemspec ADDED
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "usaidwat/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "usaidwat"
7
+ s.version = USaidWat::VERSION
8
+ s.authors = ["Michael Dippery"]
9
+ s.email = ["michael@monkey-robot.com"]
10
+ s.homepage = ""
11
+ s.summary = %q{View a user's last 100 Reddit comments}
12
+ s.description = %q{View a user's last 100 Reddit comments, organized by subreddit.}
13
+
14
+ s.rubyforge_project = "usaidwat"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_runtime_dependency 'json'
22
+ end
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: usaidwat
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Michael Dippery
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-01-24 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: json
16
+ requirement: &70171046145340 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70171046145340
25
+ description: View a user's last 100 Reddit comments, organized by subreddit.
26
+ email:
27
+ - michael@monkey-robot.com
28
+ executables:
29
+ - usaidwat
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - .gitignore
34
+ - Gemfile
35
+ - Rakefile
36
+ - bin/usaidwat
37
+ - lib/usaidwat.rb
38
+ - lib/usaidwat/reddit.rb
39
+ - lib/usaidwat/version.rb
40
+ - usaidwat.gemspec
41
+ homepage: ''
42
+ licenses: []
43
+ post_install_message:
44
+ rdoc_options: []
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ none: false
49
+ requirements:
50
+ - - ! '>='
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ! '>='
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
59
+ requirements: []
60
+ rubyforge_project: usaidwat
61
+ rubygems_version: 1.8.11
62
+ signing_key:
63
+ specification_version: 3
64
+ summary: View a user's last 100 Reddit comments
65
+ test_files: []