thimbl 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'http://rubygems.org'
2
+
3
+ group :test do
4
+ gem 'mocha'
5
+ end
data/Manifest ADDED
@@ -0,0 +1,9 @@
1
+ Gemfile
2
+ Manifest
3
+ README.md
4
+ Rakefile
5
+ lib/finger.rb
6
+ lib/thimbl.rb
7
+ test/fixtures/cache.json
8
+ test/thimbl_test.rb
9
+ thimbl.rb
data/README.md ADDED
@@ -0,0 +1,28 @@
1
+ # Thimbl Client
2
+
3
+ Is an small client for the distributed microbloging protocol: [thimbl](http://www.thimbl.net/)
4
+
5
+ ## Version
6
+
7
+ This version is in development, not ready for any production environment.
8
+
9
+ ## Install
10
+
11
+ gem install thimbl
12
+
13
+ ## Use
14
+
15
+ require 'thimbl'
16
+ thimbl = Thimbl.new( '/tmp/plan', '/tmp/thimbl_cache' )
17
+ thimbl.setup(
18
+ :bio => 'my bio',
19
+ :website => 'my website',
20
+ :mobile => 'my mobile',
21
+ :email => 'my email',
22
+ :address => 'my address',
23
+ :name => 'my name'
24
+ )
25
+ thimbl.follow 'dk', 'dk@telekommunisten.org'
26
+ thimbl.fetch
27
+ thimbl.print
28
+ thimbl.post 'My first post'
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'echoe'
4
+
5
+ Echoe.new('thimbl', '0.0.1') do |p|
6
+ p.description = "Small client for the distributed microbloging protocol: [thimbl](http://www.thimbl.net/)"
7
+ p.url = "http://github.com/fguillen/ThimblClient"
8
+ p.author = "Fernando Guillen"
9
+ p.email = "fguillen.mail@gmail.com"
10
+ p.ignore_pattern = ['etc/*']
11
+ p.development_dependencies = ['mocha', 'ruby-debug']
12
+ p.runtime_dependencies = []
13
+ end
data/lib/finger.rb ADDED
@@ -0,0 +1,5 @@
1
+ class Finger
2
+ def self.run( *args )
3
+ %x[`whereis finger` #{args.join(' ')}]
4
+ end
5
+ end
data/lib/thimbl.rb ADDED
@@ -0,0 +1,125 @@
1
+ require 'rubygems'
2
+ require 'json'
3
+ require "#{File.dirname(__FILE__)}/finger"
4
+
5
+ class Thimbl
6
+ attr_reader :plan_path, :cache_path, :data, :address
7
+
8
+ def initialize( plan_path, cache_path )
9
+ @plan_path = plan_path
10
+ @cache_path = cache_path
11
+ @data = nil
12
+ @address = nil
13
+ end
14
+
15
+ def setup( opts = {} )
16
+ opts = {
17
+ :bio => 'bio',
18
+ :website => 'website',
19
+ :mobile => 'mobile',
20
+ :email => 'email',
21
+ :address => 'address',
22
+ :name => 'name'
23
+ }.merge( opts )
24
+
25
+ @data = {
26
+ 'me' => opts[:address],
27
+ 'plans' => {
28
+ opts[:address] => {
29
+ 'name' => opts[:name],
30
+ 'bio' => opts[:bio],
31
+ 'properties' => {
32
+ 'email' => opts[:email],
33
+ 'mobile' => opts[:mobile],
34
+ 'website' => opts[:website]
35
+ },
36
+ 'following' => [],
37
+ 'messages' => [],
38
+ 'replies' => {}
39
+ }
40
+ }
41
+ }
42
+
43
+ @address = opts[:address]
44
+
45
+ save_data
46
+
47
+ return self
48
+ end
49
+
50
+ def post( text )
51
+ load_data
52
+
53
+ message = {
54
+ :address => address,
55
+ :time => Time.now.strftime('%Y%m%d%H%M%S'),
56
+ :text => text
57
+ }
58
+
59
+ data['plans'][address]['messages'] << message
60
+ save_data
61
+
62
+ return self
63
+ end
64
+
65
+ def follow( follow_nick, follow_address )
66
+ load_data
67
+ data['plans'][address]['following'] << { :nick => follow_nick, :address => follow_address }
68
+ save_data
69
+
70
+ return self
71
+ end
72
+
73
+ def fetch
74
+ load_data
75
+
76
+ following.map { |f| f['address'] }.each do |followed_address|
77
+ address_finger = Finger.run followed_address
78
+ address_plan = address_finger.match(/Plan:\s*(.*)/m)[1].gsub("\n",'')
79
+ data['plans'][followed_address] = JSON.load( address_plan )
80
+ end
81
+
82
+ save_data
83
+
84
+ return self
85
+ end
86
+
87
+ def print
88
+ load_data
89
+
90
+ result = ""
91
+ messages.each do |message|
92
+ result += Thimbl.parse_time( message['time'] ).strftime( '%Y-%m-%d %H:%M:%S' )
93
+ result += " #{message['address']}"
94
+ result += " > #{message['text']}"
95
+ result += "\n"
96
+ end
97
+
98
+ return result
99
+ end
100
+
101
+ def load_data
102
+ @data = JSON.load( File.read cache_path )
103
+ @address = data['me']
104
+ end
105
+
106
+ def save_data
107
+ File.open( cache_path, 'w' ) { |f| f.write data.to_json }
108
+ File.open( plan_path, 'w' ) { |f| f.write data['plans'][address].to_json }
109
+ end
110
+
111
+ def following
112
+ data['plans'][address]['following']
113
+ end
114
+
115
+ def messages
116
+ _messages = data['plans'].values.map { |e| e['messages'] }.flatten
117
+ _messages = _messages.sort { |a,b| a['time'] <=> b['time'] }
118
+
119
+ return _messages
120
+ end
121
+
122
+ def self.parse_time( time )
123
+ Time.utc( time[0,4], time[4,2], time[6,2], time[8,2], time[10,2], time[12,2] )
124
+ end
125
+ end
@@ -0,0 +1,146 @@
1
+ { "me" : "fguillen@telekommunisten.org",
2
+ "plans" : { "dk@telekommunisten.org" : { "address" : "dk@telekommunisten.org",
3
+ "following" : [ { "address" : "as@telekommunisten.org",
4
+ "nick" : "anthony"
5
+ },
6
+ { "address" : "ed@ping01.stura.uni-weimar.de",
7
+ "nick" : "bernd"
8
+ },
9
+ { "address" : "meschugge@ping01.stura.uni-weimar.de",
10
+ "nick" : "meschugge"
11
+ },
12
+ { "address" : "mike@mikepearce.net",
13
+ "nick" : "mike"
14
+ },
15
+ { "address" : "ww@river.styx.org",
16
+ "nick" : "ww"
17
+ },
18
+ { "address" : "spaetz@spaetz.dyndns.org",
19
+ "nick" : "spaetz"
20
+ },
21
+ { "address" : "marcell@telekommunisten.org",
22
+ "nick" : "marcell"
23
+ },
24
+ { "address" : "rw@telekommunisten.org",
25
+ "nick" : "dk"
26
+ },
27
+ { "address" : "naikodemus@telekommunisten.org",
28
+ "nick" : "n"
29
+ }
30
+ ],
31
+ "messages" : [ { "address" : "dk@telekommunisten.org",
32
+ "text" : "@bernd, would be cool to inegrate thimbl in http://bau-ha.us\\!",
33
+ "time" : "20101129060335"
34
+ },
35
+ { "address" : "dk@telekommunisten.org",
36
+ "text" : "back in berlin, call +31108208622 to here the noise created in Rotterdam",
37
+ "time" : "20101206065528"
38
+ },
39
+ { "address" : "dk@telekommunisten.org",
40
+ "text" : "What is thimbl's equivilent of #FF? In any case, follow the earliest Thimbl users: ossa@nummo.strangled.net and ed@ping01.stura.uni-weimar.de",
41
+ "time" : "20101206070601"
42
+ },
43
+ { "address" : "dk@telekommunisten.org",
44
+ "text" : "@mark, would it be better if the posts where sorted by data, and not user?",
45
+ "time" : "20101207034655"
46
+ },
47
+ { "address" : "dk@telekommunisten.org",
48
+ "text" : "@mark, not using the version I am, seems to sort by user then date, instead of just date, I tried to pull in the latest from your repo, but then the thimbl executable vanished.",
49
+ "time" : "20101207080308"
50
+ },
51
+ { "address" : "dk@telekommunisten.org",
52
+ "text" : "@mark, ok, using climbl now, posts are sorted in order. great. can't we keep the command as 'thimbl' though? it's nicer and more obvious (principal of least surprise)",
53
+ "time" : "20101207083809"
54
+ },
55
+ { "address" : "dk@telekommunisten.org",
56
+ "text" : "@mark, also a feature request, can we have a 'read' command that combines fetch+print? and unfollow would be nice (like when you make a typo in an address)",
57
+ "time" : "20101207084025"
58
+ },
59
+ { "address" : "dk@telekommunisten.org",
60
+ "text" : "@mark, or perhaps follow would first try to finger the account before adding it, to verify it's a real thimbl account?",
61
+ "time" : "20101207084116"
62
+ },
63
+ { "address" : "dk@telekommunisten.org",
64
+ "text" : "@mark, just one more thing! perhaps convert dates to GMT? Otherwise sorting is affected by timezones",
65
+ "time" : "20101207084249"
66
+ },
67
+ { "address" : "dk@telekommunisten.org",
68
+ "text" : "@mark, never mind about unfollow, I just read your blog ;)",
69
+ "time" : "20101207091343"
70
+ },
71
+ { "address" : "dk@telekommunisten.org",
72
+ "text" : "@mark, if we store the dats in GMT/UTC in the .plan, then timezones are no longer an issue",
73
+ "time" : "20101207130325"
74
+ },
75
+ { "address" : "dk@telekommunisten.org",
76
+ "text" : "@mark, great updates, your lates has been merged into the Telekommunisten repos",
77
+ "time" : "20101208104508"
78
+ },
79
+ { "address" : "dk@telekommunisten.org",
80
+ "text" : "I'm working on a new option parser for node called Operetta, will release soon",
81
+ "time" : "20101214165553"
82
+ },
83
+ { "address" : "dk@telekommunisten.org",
84
+ "text" : "just launched the new thimbl website. http://www.thimbl.net",
85
+ "time" : "20110125065111"
86
+ },
87
+ { "address" : "dk@telekommunisten.org",
88
+ "text" : "@spaetz: first response ;)",
89
+ "time" : "20110201143140"
90
+ },
91
+ { "address" : "dk@telekommunisten.org",
92
+ "text" : "@ed: have you tried frozen soup?",
93
+ "time" : "20110201143220"
94
+ },
95
+ { "address" : "dk@telekommunisten.org",
96
+ "text" : "Hello from the thimbl workshop",
97
+ "time" : "20110202152339"
98
+ },
99
+ { "address" : "dk@telekommunisten.org",
100
+ "text" : "Tonight @cbase: monochrom & Telekommunisten run DISMALWARE an antivirus toolkit for your liberal Western brain http://bit.ly/dismalware",
101
+ "time" : "20110203121940"
102
+ },
103
+ { "address" : "dk@telekommunisten.org",
104
+ "text" : "If rocker hair and skinny jeans could make comebacks, why not Finger? http://ping.fm/3C95t",
105
+ "time" : "20110203162208"
106
+ },
107
+ { "address" : "dk@telekommunisten.org",
108
+ "text" : "http://kleiner.posterous.com/last-to-chance-to-vote-for-thimbl-we-need-you",
109
+ "time" : "20110204145719"
110
+ }
111
+ ],
112
+ "name" : "Dmytri Kleiner",
113
+ "properties" : { "email" : "dk@telekommunisten.net",
114
+ "mobile" : "",
115
+ "website" : "http://www.thimbl.net"
116
+ },
117
+ "replies" : { }
118
+ },
119
+ "fguillen@telekommunisten.org" : { "address" : "fguillen@telekommunisten.org",
120
+ "following" : [ { "address" : "dk@telekommunisten.org",
121
+ "nick" : "dk"
122
+ } ],
123
+ "messages" : [ { "address" : "fguillen@telekommunisten.org",
124
+ "text" : "Here I am",
125
+ "time" : "20110131002202"
126
+ },
127
+ { "address" : "fguillen@telekommunisten.org",
128
+ "text" : "testing :)",
129
+ "time" : "20110205150637"
130
+ },
131
+ { "text" : "testing 2",
132
+ "time" : "20110205151623"
133
+ },
134
+ { "text" : "testing 3",
135
+ "time" : "20110205152247"
136
+ }
137
+ ],
138
+ "name" : "Fernando Guillen",
139
+ "properties" : { "email" : "fguillen.mail@gmail.com",
140
+ "mobile" : "N/A",
141
+ "website" : "fernandoguillen.info"
142
+ },
143
+ "replies" : { }
144
+ }
145
+ }
146
+ }
@@ -0,0 +1,89 @@
1
+ require "#{File.dirname(__FILE__)}/../thimbl"
2
+ require 'test/unit'
3
+ require 'mocha'
4
+ require 'ruby-debug'
5
+
6
+ class ThimblTest < Test::Unit::TestCase
7
+ def setup
8
+ @plan_path = '/tmp/plan'
9
+ @cache_path = '/tmp/cache'
10
+ end
11
+
12
+ def teardown
13
+ File.delete( @plan_path ) if File.exists? @plan_path
14
+ File.delete( @cache_path ) if File.exists? @cache_path
15
+ end
16
+
17
+ def test_new
18
+ thimbl = Thimbl.new( 'plan_path', 'cache_path' )
19
+ assert_equal( 'plan_path', thimbl.plan_path )
20
+ assert_equal( 'cache_path', thimbl.cache_path )
21
+ end
22
+
23
+ def test_setup_without_options
24
+ thimbl = Thimbl.new( @plan_path, @cache_path )
25
+ thimbl.setup
26
+
27
+ puts "XXX: plan: #{File.read @plan_path }"
28
+ end
29
+
30
+ def test_setup_with_options
31
+ thimbl = Thimbl.new( @plan_path, @cache_path )
32
+ thimbl.setup(
33
+ :bio => 'my bio',
34
+ :website => 'my website',
35
+ :mobile => 'my mobile',
36
+ :email => 'my email',
37
+ :address => 'my address',
38
+ :name => 'my name'
39
+ )
40
+
41
+ puts "XXX: plan: #{File.read @plan_path }"
42
+ end
43
+
44
+ def test_post
45
+ thimbl = Thimbl.new( @plan_path, @cache_path )
46
+ thimbl.setup
47
+ thimbl.post( "wadus wadus" )
48
+
49
+ puts "XXX: plan: #{File.read @plan_path }"
50
+ puts "XXX: cache: #{File.read @cache_path }"
51
+ end
52
+
53
+ def test_follow
54
+ thimbl = Thimbl.new( @plan_path, @cache_path )
55
+ thimbl.setup
56
+ thimbl.follow( 'nick', 'address' )
57
+
58
+ puts "XXX: plan: #{File.read @plan_path }"
59
+ puts "XXX: cache: #{File.read @cache_path }"
60
+ end
61
+
62
+ def test_fetch
63
+ thimbl = Thimbl.new( @plan_path, @cache_path )
64
+ thimbl.setup
65
+ thimbl.expects(:following).returns( [ {'nick' => 'pepe', 'address' => 'dk@telekommunisten.org' } ] )
66
+
67
+ puts thimbl.fetch
68
+
69
+ puts "XXX: plan: #{File.read @plan_path }"
70
+ puts "XXX: cache: #{File.read @cache_path }"
71
+ end
72
+
73
+ def test_messages
74
+ thimbl = Thimbl.new( @plan_path, "#{File.dirname(__FILE__)}/fixtures/cache.json" )
75
+ thimbl.load_data
76
+ puts thimbl.messages
77
+ end
78
+
79
+ def test_print
80
+ thimbl = Thimbl.new( @plan_path, "#{File.dirname(__FILE__)}/fixtures/cache.json" )
81
+ thimbl.load_data
82
+
83
+ puts thimbl.print
84
+ end
85
+
86
+ def test_parse_time
87
+ assert_equal( Time.utc( 2010, 11, 29, 6, 3, 35 ), Thimbl.parse_time( '20101129060335' ) )
88
+ end
89
+ end
data/thimbl.gemspec ADDED
@@ -0,0 +1,37 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{thimbl}
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 = ["Fernando Guillen"]
9
+ s.date = %q{2011-02-05}
10
+ s.description = %q{Small client for the distributed microbloging protocol: [thimbl](http://www.thimbl.net/)}
11
+ s.email = %q{fguillen.mail@gmail.com}
12
+ s.extra_rdoc_files = ["README.md", "lib/finger.rb", "lib/thimbl.rb"]
13
+ s.files = ["Gemfile", "Manifest", "README.md", "Rakefile", "lib/finger.rb", "lib/thimbl.rb", "test/fixtures/cache.json", "test/thimbl_test.rb", "thimbl.rb", "thimbl.gemspec"]
14
+ s.homepage = %q{http://github.com/fguillen/ThimblClient}
15
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Thimbl", "--main", "README.md"]
16
+ s.require_paths = ["lib"]
17
+ s.rubyforge_project = %q{thimbl}
18
+ s.rubygems_version = %q{1.3.7}
19
+ s.summary = %q{Small client for the distributed microbloging protocol: [thimbl](http://www.thimbl.net/)}
20
+ s.test_files = ["test/thimbl_test.rb"]
21
+
22
+ if s.respond_to? :specification_version then
23
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
24
+ s.specification_version = 3
25
+
26
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
27
+ s.add_development_dependency(%q<mocha>, [">= 0"])
28
+ s.add_development_dependency(%q<ruby-debug>, [">= 0"])
29
+ else
30
+ s.add_dependency(%q<mocha>, [">= 0"])
31
+ s.add_dependency(%q<ruby-debug>, [">= 0"])
32
+ end
33
+ else
34
+ s.add_dependency(%q<mocha>, [">= 0"])
35
+ s.add_dependency(%q<ruby-debug>, [">= 0"])
36
+ end
37
+ end
data/thimbl.rb ADDED
@@ -0,0 +1 @@
1
+ require "#{File.dirname(__FILE__)}/lib/thimbl"
metadata ADDED
@@ -0,0 +1,111 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: thimbl
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
+ - Fernando Guillen
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-02-05 00:00:00 +01:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: mocha
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: :development
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: ruby-debug
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: :development
48
+ version_requirements: *id002
49
+ description: "Small client for the distributed microbloging protocol: [thimbl](http://www.thimbl.net/)"
50
+ email: fguillen.mail@gmail.com
51
+ executables: []
52
+
53
+ extensions: []
54
+
55
+ extra_rdoc_files:
56
+ - README.md
57
+ - lib/finger.rb
58
+ - lib/thimbl.rb
59
+ files:
60
+ - Gemfile
61
+ - Manifest
62
+ - README.md
63
+ - Rakefile
64
+ - lib/finger.rb
65
+ - lib/thimbl.rb
66
+ - test/fixtures/cache.json
67
+ - test/thimbl_test.rb
68
+ - thimbl.rb
69
+ - thimbl.gemspec
70
+ has_rdoc: true
71
+ homepage: http://github.com/fguillen/ThimblClient
72
+ licenses: []
73
+
74
+ post_install_message:
75
+ rdoc_options:
76
+ - --line-numbers
77
+ - --inline-source
78
+ - --title
79
+ - Thimbl
80
+ - --main
81
+ - README.md
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ none: false
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ hash: 3
90
+ segments:
91
+ - 0
92
+ version: "0"
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ hash: 11
99
+ segments:
100
+ - 1
101
+ - 2
102
+ version: "1.2"
103
+ requirements: []
104
+
105
+ rubyforge_project: thimbl
106
+ rubygems_version: 1.3.7
107
+ signing_key:
108
+ specification_version: 3
109
+ summary: "Small client for the distributed microbloging protocol: [thimbl](http://www.thimbl.net/)"
110
+ test_files:
111
+ - test/thimbl_test.rb