PerfectlyNormal-Twitorious 0.2.5
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/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
|
+
|