PerfectlyNormal-Twitorious 0.2.5
Sign up to get free protection for your applications and to get access to all the features.
- data/TODO +12 -0
- data/bin/twit +29 -0
- data/bin/twit-notifier +15 -0
- data/lib/twitorious.rb +12 -0
- data/lib/twitorious/api/twitter.rb +46 -0
- data/lib/twitorious/config.rb +30 -0
- data/lib/twitorious/image.rb +33 -0
- data/lib/twitorious/notifier.rb +23 -0
- data/lib/twitorious/timeline.rb +17 -0
- data/lib/twitorious/update.rb +23 -0
- data/twitorious.gemspec +24 -0
- metadata +81 -0
data/TODO
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
* Support updating one site, a few sites, all but one site, all but a few sites, and all sites
|
2
|
+
* Support in_reply_to to send replies
|
3
|
+
* UI for displaying past updates
|
4
|
+
* Receive/send private messages
|
5
|
+
* SSL for Identi.ca authentication
|
6
|
+
* Not OS X only
|
7
|
+
* Support growling to remote machines
|
8
|
+
* Support other forms of notification (libnotify?)
|
9
|
+
* Configuration generation tool
|
10
|
+
* Error handling
|
11
|
+
* Daemon that runs in the background
|
12
|
+
* Make sure the directory for images is created
|
data/bin/twit
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'twitorious'
|
3
|
+
require 'readline'
|
4
|
+
|
5
|
+
module Twitorious
|
6
|
+
class Twit
|
7
|
+
def initialize
|
8
|
+
File.open(File.expand_path(File.join(%w{~ twit}))) do |f|
|
9
|
+
f.each_line do |line|
|
10
|
+
Readline::HISTORY.push(line.split("\t")[1])
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
begin
|
15
|
+
status = Readline.readline("> ", true)
|
16
|
+
raise Twitorious::TooLongUpdate.new(status) if status.length > 140
|
17
|
+
Twitorious::Update.new(status)
|
18
|
+
rescue Twitorious::TooLongUpdate => e
|
19
|
+
puts "Ooops, you entered more than 140 characters. #{e.message.length} to be exact."
|
20
|
+
Readline::HISTORY.push(e.message)
|
21
|
+
retry
|
22
|
+
rescue Interrupt
|
23
|
+
exit
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
Twitorious::Twit.new
|
data/bin/twit-notifier
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'twitorious'
|
3
|
+
|
4
|
+
module Twitorious
|
5
|
+
class TwitNotifier
|
6
|
+
def initialize
|
7
|
+
config = Twitorious::Config.new
|
8
|
+
timeline = Twitorious::Timeline.new(config)
|
9
|
+
|
10
|
+
timeline.fetch_timeline
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
Twitorious::TwitNotifier.new
|
data/lib/twitorious.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
module Twitorious
|
2
|
+
VERSION = '0.2.5'
|
3
|
+
|
4
|
+
class TooLongUpdate < StandardError; end
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'twitorious/config'
|
8
|
+
require 'twitorious/timeline'
|
9
|
+
require 'twitorious/update'
|
10
|
+
require 'twitorious/image'
|
11
|
+
require 'twitorious/notifier'
|
12
|
+
require 'twitorious/api/twitter'
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'json'
|
3
|
+
require 'net/http'
|
4
|
+
require 'uri'
|
5
|
+
|
6
|
+
module Twitorious
|
7
|
+
module API
|
8
|
+
class Twitter
|
9
|
+
def initialize(config, site)
|
10
|
+
@config = config
|
11
|
+
@site = site
|
12
|
+
@notifier = Twitorious::Notifier.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def update(status)
|
16
|
+
puts "Updating #{@site[:name]}"
|
17
|
+
req = Net::HTTP::Post.new(@site[:url].path + "/statuses/update.json")
|
18
|
+
req.basic_auth @site[:user], @site[:pass]
|
19
|
+
req.set_form_data({'status' => status}, ';')
|
20
|
+
res = Net::HTTP.new(@site[:url].host, @site[:url].port).start { |http| http.request(req) }
|
21
|
+
end
|
22
|
+
|
23
|
+
def fetch_timeline
|
24
|
+
res = nil
|
25
|
+
Net::HTTP.start(@site[:url].host, @site[:url].port) do |http|
|
26
|
+
path = @site[:url].path + "/statuses/friends_timeline.json"
|
27
|
+
path += "?count=200&since_id=#{@site[:since_id]}" if @site[:since_id]
|
28
|
+
req = Net::HTTP::Get.new(path)
|
29
|
+
req.basic_auth @site[:user], @site[:pass]
|
30
|
+
res = http.request(req)
|
31
|
+
end
|
32
|
+
|
33
|
+
updates = JSON.parse(res.body)
|
34
|
+
return if updates.empty?
|
35
|
+
|
36
|
+
updates.reverse.each do |update|
|
37
|
+
image = Twitorious::Image.from_url(update["user"]["profile_image_url"], @config.image_store)
|
38
|
+
@notifier.notify(update["user"]["screen_name"], update["text"], image.filename)
|
39
|
+
sleep @config.sleep_between_notifications.to_i
|
40
|
+
end
|
41
|
+
|
42
|
+
@site[:since_id] = updates[0]["id"]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Twitorious
|
2
|
+
class Config
|
3
|
+
def initialize
|
4
|
+
@file = File.expand_path(File.join(['~', '.twitorious']))
|
5
|
+
@config = YAML.load_file(@file)
|
6
|
+
end
|
7
|
+
|
8
|
+
def [](key)
|
9
|
+
return @config[key] if @config.has_key?(key)
|
10
|
+
return nil
|
11
|
+
end
|
12
|
+
|
13
|
+
def []=(key, value)
|
14
|
+
@config[key] = value
|
15
|
+
return @config[key]
|
16
|
+
end
|
17
|
+
|
18
|
+
def save
|
19
|
+
File.open(@file, "w") do |f|
|
20
|
+
f.puts @config.to_yaml
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def method_missing(sym, *args)
|
25
|
+
return @config[sym] if @config.has_key?(sym)
|
26
|
+
super(sym, args)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'net/http'
|
3
|
+
require 'digest/md5'
|
4
|
+
|
5
|
+
module Twitorious
|
6
|
+
class Image
|
7
|
+
attr_reader :filename
|
8
|
+
|
9
|
+
def initialize(filename)
|
10
|
+
@filename = filename
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.from_url(url, store)
|
14
|
+
file = Digest::MD5.hexdigest(url).to_s
|
15
|
+
path = File.expand_path(File.join([store, file]))
|
16
|
+
|
17
|
+
if(File.exists?(path))
|
18
|
+
return Image.new(path)
|
19
|
+
end
|
20
|
+
|
21
|
+
site = URI.parse(url)
|
22
|
+
res = Net::HTTP.start(site.host, site.port) do |http|
|
23
|
+
http.get(site.path)
|
24
|
+
end
|
25
|
+
|
26
|
+
File.open(path, "wb+") do |f|
|
27
|
+
f.puts res.body
|
28
|
+
end
|
29
|
+
|
30
|
+
return Image.new(path)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'meow'
|
3
|
+
require 'uri'
|
4
|
+
|
5
|
+
module Twitorious
|
6
|
+
class Notifier
|
7
|
+
def initialize
|
8
|
+
@meow = Meow.new("Twitorious")
|
9
|
+
end
|
10
|
+
|
11
|
+
def notify(sender, message, icon = nil)
|
12
|
+
opts = {}
|
13
|
+
opts[:icon] = icon if icon
|
14
|
+
|
15
|
+
@meow.notify("Update from #{sender}", message, opts) do
|
16
|
+
urls = URI.extract(message, ['http', 'https'])
|
17
|
+
urls.each do |url|
|
18
|
+
%x{open #{url}}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Twitorious
|
2
|
+
class Timeline
|
3
|
+
def initialize(config)
|
4
|
+
@config = config
|
5
|
+
end
|
6
|
+
|
7
|
+
def fetch_timeline
|
8
|
+
@config.sites.each do |site|
|
9
|
+
case site[:api]
|
10
|
+
when "Twitter": Twitorious::API::Twitter.new(@config, site).fetch_timeline
|
11
|
+
else puts "Unknown API #{site[:api]} for site #{site[:name]}"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
@config.save # Since we've gotten newer since_id's
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Twitorious
|
2
|
+
class Update
|
3
|
+
def initialize(status, config = nil)
|
4
|
+
@status = status.to_s
|
5
|
+
@config = config
|
6
|
+
@config = Twitorious::Config.new unless @config
|
7
|
+
|
8
|
+
@config.sites.each do |site|
|
9
|
+
case site[:api]
|
10
|
+
when "Twitter": Twitorious::API::Twitter.new(@config, site).update(status)
|
11
|
+
else puts "Unknown API #{site[:api]} for site #{site[:name]}"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
save_update
|
15
|
+
end
|
16
|
+
|
17
|
+
def save_update
|
18
|
+
File.open(File.expand_path(@config.update_store), "a+") do |f|
|
19
|
+
f.puts "#{Time.now.to_i}\t#{@status}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/twitorious.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "Twitorious"
|
3
|
+
s.version = "0.2.5"
|
4
|
+
s.date = "2009-03-23"
|
5
|
+
s.author = "Per Christian B. Viken"
|
6
|
+
s.email = "perchr@northblue.org"
|
7
|
+
s.homepage = "http://eastblue.org/projects/twitorious/"
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.summary = "A simple microblogging client that can post updates, and display received updates"
|
10
|
+
s.files = ["twitorious.gemspec",
|
11
|
+
"lib/twitorious.rb",
|
12
|
+
"lib/twitorious/config.rb",
|
13
|
+
"lib/twitorious/image.rb",
|
14
|
+
"lib/twitorious/timeline.rb",
|
15
|
+
"lib/twitorious/update.rb",
|
16
|
+
"lib/twitorious/notifier.rb",
|
17
|
+
"lib/twitorious/api/twitter.rb",
|
18
|
+
"TODO"]
|
19
|
+
s.executables << 'twit'
|
20
|
+
s.executables << 'twit-notifier'
|
21
|
+
s.add_dependency("meow", ">= 2.1.0")
|
22
|
+
s.add_dependency("json", ">= 1.1.0")
|
23
|
+
s.has_rdoc = true
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: PerfectlyNormal-Twitorious
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.5
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Per Christian B. Viken
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-03-23 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: meow
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 2.1.0
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: json
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.1.0
|
34
|
+
version:
|
35
|
+
description:
|
36
|
+
email: perchr@northblue.org
|
37
|
+
executables:
|
38
|
+
- twit
|
39
|
+
- twit-notifier
|
40
|
+
extensions: []
|
41
|
+
|
42
|
+
extra_rdoc_files: []
|
43
|
+
|
44
|
+
files:
|
45
|
+
- twitorious.gemspec
|
46
|
+
- lib/twitorious.rb
|
47
|
+
- lib/twitorious/config.rb
|
48
|
+
- lib/twitorious/image.rb
|
49
|
+
- lib/twitorious/timeline.rb
|
50
|
+
- lib/twitorious/update.rb
|
51
|
+
- lib/twitorious/notifier.rb
|
52
|
+
- lib/twitorious/api/twitter.rb
|
53
|
+
- TODO
|
54
|
+
has_rdoc: true
|
55
|
+
homepage: http://eastblue.org/projects/twitorious/
|
56
|
+
post_install_message:
|
57
|
+
rdoc_options: []
|
58
|
+
|
59
|
+
require_paths:
|
60
|
+
- lib
|
61
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: "0"
|
66
|
+
version:
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: "0"
|
72
|
+
version:
|
73
|
+
requirements: []
|
74
|
+
|
75
|
+
rubyforge_project:
|
76
|
+
rubygems_version: 1.2.0
|
77
|
+
signing_key:
|
78
|
+
specification_version: 2
|
79
|
+
summary: A simple microblogging client that can post updates, and display received updates
|
80
|
+
test_files: []
|
81
|
+
|