thimbl 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/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