gephi_keeper 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ === 0.0.1 2011-10-30
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
@@ -0,0 +1,15 @@
1
+ History.txt
2
+ Manifest.txt
3
+ PostInstall.txt
4
+ README.rdoc
5
+ Rakefile
6
+ bin/gephi_keeper
7
+ lib/gephi_keeper.rb
8
+ lib/gephi_keeper/base.rb
9
+ lib/gephi_keeper/cli.rb
10
+ script/console
11
+ script/destroy
12
+ script/generate
13
+ test/test_gephi_keeper.rb
14
+ test/test_gephi_keeper_cli.rb
15
+ test/test_helper.rb
@@ -0,0 +1 @@
1
+ Gratz! You can now run 'gephi_keeper -f FILENAME'
@@ -0,0 +1,85 @@
1
+ = gephi_keeper
2
+
3
+ * http://github.com/cmdjohnson/gephi_keeper
4
+
5
+ == DESCRIPTION:
6
+
7
+ gephi_keeper is a Ruby conversion gem that links YourTwapperKeeper (http://your.twapperkeeper.com/) to Gephi (http://www.gephi.org) by converting JSON output from YTK to Gephi's GEXF format.
8
+
9
+ YourTwapperKeeper is a self-hosted service that archives tweets. Gephi is a graph visualization tool. YTK exports the archived tweets in a number of formats, one of which is JSON. The JSON files produced by YTK are converted by gephi_keeper into Gephi-readable GEXF files.
10
+
11
+ The GEXF files can then be processed by Gephi to produce colorful graph representations of Twitter output.
12
+
13
+ == FEATURES/PROBLEMS:
14
+
15
+ - Dynamic graphs: use the Gephi timeline to watch the network evolve over time.
16
+ - Attributes: Number of tweets per user, number of mentions per user.
17
+ - Node color is based on Twitter activity: a very active user is colored red whilst a not-so-active user is black.
18
+ - Node size is based on other Twitter users' activity: a user that is mentioned many times is larger than a user that is not.
19
+ - Parents: when user A mentions user B, user B becomes A's parent.
20
+ - Edges are plotted automatically between interacting users: when user A mentions user B, an edge is created.
21
+ - Edge weight is based on the activity from user A to user B. When user A mentions B many times, the edge weight in increased.
22
+
23
+ == SYNOPSIS:
24
+
25
+ Input a file into gephi_keeper and pipe the output to a gzipped output file:
26
+
27
+ $ gephi_keeper -f input_file.json | gzip > output_file.gexf.gz
28
+
29
+ == REQUIREMENTS:
30
+
31
+ gephi_keeper needs these gems in order to run properly:
32
+ - json (for JSON input)
33
+ - options_checker
34
+ - builder (for XML output)
35
+
36
+ == INSTALL:
37
+
38
+ $ sudo gem install gephi_keeper
39
+
40
+ == EXAMPLES:
41
+
42
+ Screenshots:
43
+
44
+ https://github.com/cmdjohnson/gephi_keeper/raw/master/examples/screenshots/twitter_gephi_keeper_1.png
45
+
46
+ https://github.com/cmdjohnson/gephi_keeper/raw/master/examples/screenshots/twitter_gephi_keeper_2.png
47
+
48
+ Recipe used for the screenshots:
49
+ 1. Import oracle.gexf
50
+ 2. Layout: Fruchterman Reingold
51
+ 3. Enable labels
52
+ 4. Rank label size based on num_mentions, min_size = 0.5 and max_size = 3
53
+
54
+ Example Gephi files:
55
+
56
+ Hashtag #oracle (3,000 tweets) https://github.com/cmdjohnson/gephi_keeper/raw/master/examples/output/oracle.gexf.gz
57
+
58
+ Hashtag #java (5,000 tweets) https://github.com/cmdjohnson/gephi_keeper/raw/master/examples/output/java.gexf.gz
59
+
60
+ Hashtag #twitter (10,000 tweets) https://github.com/cmdjohnson/gephi_keeper/raw/master/examples/output/twitter.gexf.gz
61
+
62
+ == LICENSE:
63
+
64
+ (The MIT License)
65
+
66
+ Copyright (c) 2011 Commander Johnson <commanderjohnson@gmail.com>
67
+
68
+ Permission is hereby granted, free of charge, to any person obtaining
69
+ a copy of this software and associated documentation files (the
70
+ 'Software'), to deal in the Software without restriction, including
71
+ without limitation the rights to use, copy, modify, merge, publish,
72
+ distribute, sublicense, and/or sell copies of the Software, and to
73
+ permit persons to whom the Software is furnished to do so, subject to
74
+ the following conditions:
75
+
76
+ The above copyright notice and this permission notice shall be
77
+ included in all copies or substantial portions of the Software.
78
+
79
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
80
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
81
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
82
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
83
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
84
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
85
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,26 @@
1
+ require 'rubygems'
2
+ gem 'hoe', '>= 2.1.0'
3
+ require 'hoe'
4
+ require 'fileutils'
5
+ require './lib/gephi_keeper'
6
+
7
+ Hoe.plugin :newgem
8
+ # Hoe.plugin :website
9
+ # Hoe.plugin :cucumberfeatures
10
+
11
+ # Generate all the Rake tasks
12
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
13
+ $hoe = Hoe.spec 'gephi_keeper' do
14
+ self.developer 'Commander Johnson', 'commanderjohnson@gmail.com'
15
+ self.post_install_message = 'PostInstall.txt'
16
+ self.rubyforge_name = self.name
17
+ self.extra_deps = [ "json", "options_checker", "builder" ]
18
+
19
+ end
20
+
21
+ require 'newgem/tasks'
22
+ Dir['tasks/**/*.rake'].each { |t| load t }
23
+
24
+ # TODO - want other tests/tasks run by default? Add them to the list
25
+ # remove_task :default
26
+ # task :default => [:spec, :features]
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Created by Commander Johnson on 2011-10-30.
4
+ # Copyright (c) 2011. All rights reserved.
5
+
6
+ require 'rubygems'
7
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/gephi_keeper")
8
+ require "gephi_keeper/cli"
9
+
10
+ GephiKeeper::CLI.execute(STDOUT, ARGV)
@@ -0,0 +1,6 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ module GephiKeeper
5
+ VERSION = '0.0.1'
6
+ end
@@ -0,0 +1,301 @@
1
+ require 'rubygems'
2
+ # json
3
+ require 'json'
4
+ # options_checker
5
+ require 'options_checker'
6
+ # builder
7
+ require 'builder'
8
+ # time
9
+ # for 'parse'
10
+ require 'time'
11
+
12
+ module GephiKeeper
13
+ class Base
14
+ def self.process_file(options = {})
15
+ OptionsChecker.check(options, [ :filename ])
16
+
17
+ ##########################################################################
18
+ # initialize
19
+ ##########################################################################
20
+
21
+ # Get file object
22
+ file = File.new(options[:filename])
23
+ # Load the file into memory. Could be costly when files are too big ...
24
+ json = JSON.parse(file.read)
25
+
26
+ ##########################################################################
27
+ # metadata
28
+ ##########################################################################
29
+
30
+ # Metadata
31
+ create_time = json["archive_info"]["create_time"]
32
+ tags = json["archive_info"]["tags"]
33
+ id = json["archive_info"]["id"]
34
+ count = json["archive_info"]["count"]
35
+ user_id = json["archive_info"]["user_id"]
36
+ description = json["archive_info"]["description"]
37
+ keyword = json["archive_info"]["keyword"]
38
+ screen_name = json["archive_info"]["screen_name"]
39
+
40
+ ##########################################################################
41
+ # process tweets
42
+ ##########################################################################
43
+
44
+ # les tweets
45
+ tweets = json["tweets"]
46
+
47
+ start_time = Time.parse(tweets.last["created_at"])
48
+ end_time = Time.parse(tweets.first["created_at"])
49
+ converted_start_time = convert_time_to_gexf_integer(start_time)
50
+ converted_end_time = convert_time_to_gexf_integer(end_time)
51
+
52
+ # We will convert to this
53
+ nodes = {}
54
+ edges = {}
55
+ # Generic attributes for each node in this population.
56
+ attributes = []
57
+ # Define attributes.
58
+ attributes.push({ :title => "num_tweets", :type => "integer" })
59
+ attributes.push({ :title => "num_mentions", :type => "integer" })
60
+
61
+ # But use this indirect representation first.
62
+ # +_+ #
63
+ occurrences ||= {}
64
+ # Count the number of mentions with this hash.
65
+ mentions ||= {}
66
+
67
+ # Example json tweet:
68
+ #{"archivesource":"twitter-search",
69
+ #"text":"RT @netbeans: Building a simple AtomPub client w #NetBeans, #Maven, #Java &amp; #Apache Abdera: http:\/\/t.co\/NQcUi32k",
70
+ #"to_user_id":"",
71
+ #"from_user":"banumelody",
72
+ #"id":"129498621086408704",
73
+ #"from_user_id":"277264632",
74
+ #"iso_language_code":"en",
75
+ #"source":"&lt;a href=&quot;http:\/\/www.hootsuite.com&quot; rel=&quot;nofollow&quot;&gt;HootSuite&lt;\/a&gt;",
76
+ #"profile_image_url":"http:\/\/a1.twimg.com\/profile_images\/1605902800\/Hytgs0pn_normal",
77
+ #"geo_type":"",
78
+ #"geo_coordinates_0":"0",
79
+ #"geo_coordinates_1":"0",
80
+ #"created_at":"Thu, 27 Oct 2011 10:04:11 +0000",
81
+ #"time":"1319709851"}
82
+
83
+ # Convert to a workable internal representation.
84
+ for tweet in tweets
85
+ #nodes.push({ :id => tweet["from_user_id"], :label => tweet["from_user"] })
86
+ # Don't distinguish oracle and Oracle.
87
+ username = tweet["from_user"].downcase
88
+ # Make the hash if it wasn't already there.
89
+ occurrences[username] ||= {}
90
+ o = occurrences[username]
91
+ # Count the number of times this user exists in this export
92
+ o ||= {}
93
+ # Tweet array.
94
+ o[:tweets] ||= []
95
+ # Now push this tweet occurence to that user.
96
+ o[:tweets].push(tweet)
97
+
98
+ # Check for the first tweet from this user.
99
+ # We are only interested in the date of the first tweet and none other.
100
+ # +_+ #
101
+ parsed_time = Time.parse(tweet["created_at"])
102
+ # Was it before the existing tweet, if any?
103
+ if o[:first_tweeted_at].nil?
104
+ my_parsed_time = parsed_time
105
+ else
106
+ my_parsed_time = parsed_time if parsed_time < o[:first_tweeted_at]
107
+ end
108
+ # +_+ #
109
+ o[:first_tweeted_at] = my_parsed_time
110
+
111
+ # Extract references.
112
+ o[:references] ||= {}
113
+ # All references in this tweet.
114
+ # +_+ #
115
+ refs = tweet["text"].scan(/@(\w+)/) # => [["netbeans"], ["zozo"], ["bozozo"]]
116
+ # +_+ #
117
+ for ref in refs
118
+ # Oracle is the same as oracle
119
+ my_ref = ref.first.downcase
120
+ # Also add this user to the nodes list.
121
+ occurrences[my_ref] ||= {}
122
+ occurrences[my_ref][:first_tweeted_at] ||= my_parsed_time
123
+ # +_+ #
124
+ o[:references][my_ref] ||= { :count => 0 }
125
+ ref_p = o[:references][my_ref]
126
+ # Increase count.
127
+ ref_p[:count] += 1
128
+ # Also increase the count of the global mentions in this population.
129
+ mentions[my_ref] ||= 0
130
+ # +_+ #
131
+ mentions[my_ref] += 1
132
+ end
133
+ end
134
+
135
+ ##########################################################################
136
+ # Data structure:
137
+ #
138
+ # occurrences
139
+ # - [username]
140
+ # - :tweets Array of tweets (Hash objects)
141
+ # - :first_tweeted_at Time object when the first tweet from this user was registered.
142
+ # - :references Hash of usernames (String) mentioned by this user in any tweet
143
+ # - [username]
144
+ # - :count Number of times referred to username in any tweet
145
+ ##########################################################################
146
+
147
+ # Now convert to nodes & edges
148
+ occurrences.keys.each do |key|
149
+ # +_+ #
150
+ node_options = {}
151
+ # +_+ #
152
+ num_tweets = 0
153
+ # +_+ #
154
+ begin
155
+ num_tweets = occurrences[key][:tweets].count
156
+ rescue
157
+ end
158
+ # +_+ #
159
+ num_mentions = mentions[key] || 0
160
+ # +_+ #
161
+ node_options = { :attributes => {
162
+ :id => key,
163
+ :label => key,
164
+ :start => convert_time_to_gexf_integer(occurrences[key][:first_tweeted_at]),
165
+ :end => converted_end_time
166
+ },
167
+ :size => num_mentions,
168
+ :intensity => num_tweets,
169
+ :attvalues => [
170
+ # 0 = tweets, 1 = mentions
171
+ { :value => num_tweets, :for => "0" },
172
+ { :value => num_mentions, :for => "1" }
173
+ ]
174
+ }
175
+ # Now using Hash instead of Array
176
+ nodes[key] = node_options
177
+ # +_+ #
178
+ if occurrences[key][:references]
179
+ occurrences[key][:references].keys.each do |reference|
180
+ # +_+ #
181
+ edge_key = "#{key}-#{reference}"
182
+ # +_+ #
183
+ reference_count = occurrences[key][:references][reference][:count]
184
+ # +_+ #
185
+ edges[edge_key] = { :id => edge_key, :source => key,
186
+ :target => reference,
187
+ :weight => reference_count,
188
+ :label => reference_count
189
+ }
190
+ end
191
+ end
192
+ end
193
+
194
+ ##########################################################################
195
+ # output xml
196
+ #
197
+ # fuck xmlsimple. Hashes don't order too well.
198
+ ##########################################################################
199
+
200
+ now = Time.now
201
+ xml_last_modified_date = convert_time_to_gexf_date(now)
202
+ xml_creator = screen_name
203
+ xml_description = "gephi_keeper GEXF output for keyword '#{keyword}' at (#{xml_last_modified_date}). Tags: '#{tags}'. Number of tweets: #{count}. Description: #{description}"
204
+
205
+ # nodes = [
206
+ # { :id => 0, :label => "Hello" },
207
+ # { :id => 1, :label => "World" } ]
208
+ # edges = [
209
+ # { :id => 0, :source => 0, :target => 1 }
210
+ # ]
211
+
212
+ xml = Builder::XmlMarkup.new( :target => $stdout, :indent => 2 )
213
+
214
+ xml.instruct! :xml, :version => "1.0", :encoding => "UTF-8"
215
+
216
+ xml.gexf :xmlns => "http://www.gexf.net/1.1", :version => "1.1", "xmlns:viz" => "http://www.gexf.net/1.1draft/viz" do
217
+ xml.graph :mode => "dynamic", :start => converted_start_time, :end => converted_end_time, :timeformat => "integer" do
218
+ xml.meta :lastmodifieddate => xml_last_modified_date do
219
+ xml.creator xml_creator
220
+ xml.description xml_description
221
+ end
222
+ xml.attributes :class => :node do
223
+ for attribute in attributes
224
+ xml_attribute_options = { :id => attributes.index(attribute) }
225
+ xml.attribute xml_attribute_options.merge(attribute)
226
+ end
227
+ end
228
+ xml.nodes do
229
+ nodes.each do |key, node|
230
+ # ATTRIBUTES ATTRIBUTES ATTRIBUTES ATTRIBUTES ATTRIBUTES ATTRIBUTES
231
+ xml.node node[:attributes] do
232
+ # VIZ VIZ VIZ VIZ VIZ VIZ VIZ VIZ VIZ VIZ VIZ VIZ VIZ VIZ VIZ VIZ
233
+ xml.viz :size, :value => node[:size]
234
+ xml.viz :color, intensity_to_gexf_color(node[:intensity])
235
+ # ATTVALUES ATTVALUES ATTVALUES ATTVALUES ATTVALUES ATTVALUES ATTVALUES
236
+ xml.attvalues do
237
+ for attvalue in node[:attvalues]
238
+ xml.attvalue attvalue
239
+ end
240
+ end
241
+ # PARENTS PARENTS PARENTS PARENTS PARENTS PARENTS PARENTS PARENTS
242
+ if occurrences[key][:references]
243
+ unless occurrences[key][:references].keys.count.eql?(0)
244
+ xml.parents do
245
+ occurrences[key][:references].keys.each do |reference|
246
+ xml.parent :for => reference
247
+ end
248
+ end
249
+ end
250
+ end
251
+ end
252
+ end
253
+ end
254
+ xml.edges do
255
+ edges.each do |key, edge|
256
+ xml.edge edge
257
+ end
258
+ end
259
+ end
260
+ end
261
+
262
+ ##########################################################################
263
+ # fin
264
+ ##########################################################################
265
+
266
+ true
267
+ end
268
+
269
+ protected
270
+
271
+ def self.convert_time_to_gexf_date(time)
272
+ raise "Need Time object" unless time.is_a? Time
273
+
274
+ "#{time.year}-#{time.month}-#{time.day}"
275
+ end
276
+
277
+ def self.convert_time_to_gexf_integer(time)
278
+ raise "Need Time object" unless time.is_a? Time
279
+
280
+ time.to_i
281
+ end
282
+
283
+ def self.intensity_to_gexf_color(intensity)
284
+ r = 0
285
+ g = 0
286
+ b = 0
287
+ a = 0.7
288
+
289
+ r_increment = 10 * intensity
290
+ r_increment = 255 if r_increment > 255
291
+ r += r_increment
292
+
293
+ a_increment = 0.01 * intensity
294
+
295
+ a_increment = 0.3 if a_increment > 0.3
296
+ a += a_increment
297
+
298
+ { :r => r, :g => g, :b => b, :a => a }
299
+ end
300
+ end
301
+ end
@@ -0,0 +1,41 @@
1
+ require 'optparse'
2
+ require 'gephi_keeper/base'
3
+
4
+ module GephiKeeper
5
+ class CLI
6
+ def self.execute(stdout, arguments=[])
7
+
8
+ # Defaults for options
9
+ options = {
10
+ :filename => nil
11
+ }
12
+ mandatory_options = [ :filename ]
13
+
14
+ parser = OptionParser.new do |opts|
15
+ opts.banner = <<-BANNER.gsub(/^ /,'')
16
+ Convert tweets from Twitter, output as JSON from TwapperKeeper (www.twapperkeeper.com) into GEXF format for the Gephi graphviz tool. (www.gephi.org)
17
+
18
+ Usage: #{File.basename($0)} [options]
19
+
20
+ Options are:
21
+ BANNER
22
+ opts.separator ""
23
+ opts.on("-f", "--filename FILENAME", String,
24
+ "Name of input file.") { |arg| options[:filename] = arg }
25
+ opts.on("-h", "--help",
26
+ "Show this help message.") { stdout.puts opts; exit }
27
+ opts.parse!(arguments)
28
+ # Check for mandatory options
29
+ if mandatory_options && mandatory_options.find { |option| options[option.to_sym].nil? }
30
+ stdout.puts opts; exit
31
+ end
32
+ end
33
+
34
+ filename = options[:filename]
35
+
36
+ # do stuff
37
+ #stdout.puts "To update this executable, look in lib/gephi_keeper/cli.rb"
38
+ GephiKeeper::Base.process_file( :filename => filename )
39
+ end
40
+ end
41
+ end
@@ -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/gephi_keeper.rb'}"
9
+ puts "Loading gephi_keeper gem"
10
+ exec "#{irb} #{libs} --simple-prompt"
@@ -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)
@@ -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,11 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class TestGephiKeeper < Test::Unit::TestCase
4
+
5
+ def setup
6
+ end
7
+
8
+ def test_truth
9
+ assert true
10
+ end
11
+ end
@@ -0,0 +1,14 @@
1
+ require File.join(File.dirname(__FILE__), "test_helper.rb")
2
+ require 'gephi_keeper/cli'
3
+
4
+ class TestGephiKeeperCli < Test::Unit::TestCase
5
+ def setup
6
+ GephiKeeper::CLI.execute(@stdout_io = StringIO.new, [])
7
+ @stdout_io.rewind
8
+ @stdout = @stdout_io.read
9
+ end
10
+
11
+ def test_print_default_output
12
+ assert_match(/To update this executable/, @stdout)
13
+ end
14
+ end
@@ -0,0 +1,3 @@
1
+ require 'stringio'
2
+ require 'test/unit'
3
+ require File.dirname(__FILE__) + '/../lib/gephi_keeper'
metadata ADDED
@@ -0,0 +1,149 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gephi_keeper
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Commander Johnson
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-11-25 00:00:00 +01:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: json
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: options_checker
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :runtime
48
+ version_requirements: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ name: builder
51
+ prerelease: false
52
+ requirement: &id003 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ hash: 3
58
+ segments:
59
+ - 0
60
+ version: "0"
61
+ type: :runtime
62
+ version_requirements: *id003
63
+ - !ruby/object:Gem::Dependency
64
+ name: hoe
65
+ prerelease: false
66
+ requirement: &id004 !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ hash: 47
72
+ segments:
73
+ - 2
74
+ - 8
75
+ - 0
76
+ version: 2.8.0
77
+ type: :development
78
+ version_requirements: *id004
79
+ description: |-
80
+ gephi_keeper is a Ruby conversion gem that links YourTwapperKeeper (http://your.twapperkeeper.com/) to Gephi (http://www.gephi.org) by converting JSON output from YTK to Gephi's GEXF format.
81
+
82
+ YourTwapperKeeper is a self-hosted service that archives tweets. Gephi is a graph visualization tool. YTK exports the archived tweets in a number of formats, one of which is JSON. The JSON files produced by YTK are converted by gephi_keeper into Gephi-readable GEXF files.
83
+
84
+ The GEXF files can then be processed by Gephi to produce colorful graph representations of Twitter output.
85
+ email:
86
+ - commanderjohnson@gmail.com
87
+ executables:
88
+ - gephi_keeper
89
+ extensions: []
90
+
91
+ extra_rdoc_files:
92
+ - History.txt
93
+ - Manifest.txt
94
+ - PostInstall.txt
95
+ files:
96
+ - History.txt
97
+ - Manifest.txt
98
+ - PostInstall.txt
99
+ - README.rdoc
100
+ - Rakefile
101
+ - bin/gephi_keeper
102
+ - lib/gephi_keeper.rb
103
+ - lib/gephi_keeper/base.rb
104
+ - lib/gephi_keeper/cli.rb
105
+ - script/console
106
+ - script/destroy
107
+ - script/generate
108
+ - test/test_gephi_keeper.rb
109
+ - test/test_gephi_keeper_cli.rb
110
+ - test/test_helper.rb
111
+ has_rdoc: true
112
+ homepage: http://github.com/cmdjohnson/gephi_keeper
113
+ licenses: []
114
+
115
+ post_install_message: PostInstall.txt
116
+ rdoc_options:
117
+ - --main
118
+ - README.rdoc
119
+ require_paths:
120
+ - lib
121
+ required_ruby_version: !ruby/object:Gem::Requirement
122
+ none: false
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ hash: 3
127
+ segments:
128
+ - 0
129
+ version: "0"
130
+ required_rubygems_version: !ruby/object:Gem::Requirement
131
+ none: false
132
+ requirements:
133
+ - - ">="
134
+ - !ruby/object:Gem::Version
135
+ hash: 3
136
+ segments:
137
+ - 0
138
+ version: "0"
139
+ requirements: []
140
+
141
+ rubyforge_project: gephi_keeper
142
+ rubygems_version: 1.3.7
143
+ signing_key:
144
+ specification_version: 3
145
+ summary: gephi_keeper is a Ruby conversion gem that links YourTwapperKeeper (http://your.twapperkeeper.com/) to Gephi (http://www.gephi.org) by converting JSON output from YTK to Gephi's GEXF format
146
+ test_files:
147
+ - test/test_gephi_keeper.rb
148
+ - test/test_gephi_keeper_cli.rb
149
+ - test/test_helper.rb