fxtwitter 0.1.0

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/History.txt ADDED
@@ -0,0 +1,13 @@
1
+ === 1.0.0 / 2008-03-15
2
+
3
+ * 4 major enhancement
4
+
5
+ * Birthday!
6
+ * Read your friends' Tweets
7
+ * Post your own Tweets
8
+ * Character counter lets you know that your Tweet is short enough.
9
+
10
+ * 1 major limitation
11
+
12
+ * No tests!
13
+
data/Manifest.txt ADDED
@@ -0,0 +1,7 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ bin/fxtwitter
6
+ lib/fxtwitter.rb
7
+ test/test_fxtwitter.rb
data/README.txt ADDED
@@ -0,0 +1,56 @@
1
+ = fxtwitter
2
+
3
+ * http://projects.rubyforge.org/fxtwitte
4
+
5
+ == DESCRIPTION:
6
+
7
+ fxtwitter is a GUI client for the Twitter <http://twitter.com> system.
8
+ It provides a simple interface comparable to many popular instant
9
+ messaging chat clients.
10
+
11
+ == FEATURES/PROBLEMS:
12
+
13
+ * View the recent tweets of all your friends in a scrolled window
14
+ * Post your own tweets
15
+
16
+ == SYNOPSIS:
17
+
18
+ The fxtwitter executable should be installed in a file on your path. Running
19
+ the application after installation should be easy:
20
+
21
+ $ fxtwitter -u USERNAME -p PASSWORD
22
+
23
+ == REQUIREMENTS:
24
+
25
+ * Ruby (developed on 1.8.6)
26
+ * Twitter4R (developed with 0.3.0)
27
+ * FXRuby (developed with 1.6.13)
28
+
29
+ == INSTALL:
30
+
31
+ $ sudo gem install fxtwitter
32
+
33
+ == LICENSE:
34
+
35
+ (The MIT License)
36
+
37
+ Copyright (c) 2008 Brian Wisti
38
+
39
+ Permission is hereby granted, free of charge, to any person obtaining
40
+ a copy of this software and associated documentation files (the
41
+ 'Software'), to deal in the Software without restriction, including
42
+ without limitation the rights to use, copy, modify, merge, publish,
43
+ distribute, sublicense, and/or sell copies of the Software, and to
44
+ permit persons to whom the Software is furnished to do so, subject to
45
+ the following conditions:
46
+
47
+ The above copyright notice and this permission notice shall be
48
+ included in all copies or substantial portions of the Software.
49
+
50
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
51
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
52
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
53
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
54
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
55
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
56
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+ require './lib/fxtwitter.rb'
6
+
7
+ Hoe.new('fxtwitter', FxTwitter::VERSION) do |p|
8
+ p.developer('Brian Wisti', 'brianwisti@rubyforge.org')
9
+ p.extra_deps << [ 'fxruby' ]
10
+ p.extra_deps << [ 'twitter4r' ]
11
+ end
12
+
13
+ # vim: syntax=Ruby
data/bin/fxtwitter ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'fxtwitter'
5
+
6
+ FxTwitter.main()
7
+
8
+ #vim:set filetype=ruby
data/lib/fxtwitter.rb ADDED
@@ -0,0 +1,187 @@
1
+ require 'rubygems'
2
+ require 'cgi'
3
+ require 'fox16'
4
+ require 'fox16/colors'
5
+ require 'time'
6
+ require 'twitter'
7
+
8
+ include Fox
9
+
10
+ class FxTwitter
11
+ VERSION = '0.1.0'
12
+ TWEET_LENGTH = 140 # Twitter allows this many characters at most.
13
+
14
+ # The primary user interface for fxtwitter
15
+ class TwitterWindow < Fox::FXMainWindow
16
+ include Fox
17
+ def initialize(app, username, password)
18
+ super(app, "fxtwitter", nil, nil,
19
+ :opts => DECOR_TITLE | DECOR_CLOSE | DECOR_RESIZE,
20
+ :width => 480)
21
+ @username = username
22
+ @password = password
23
+
24
+ # Put together UI elements
25
+ @tweet_display = FXText.new(self,
26
+ :opts => LAYOUT_FIX_WIDTH | LAYOUT_FIX_HEIGHT |
27
+ LAYOUT_FILL_X | LAYOUT_FILL_Y |
28
+ TEXT_READONLY | TEXT_WORDWRAP,
29
+ :width => 480, :height => 200)
30
+
31
+ @control_frame = FXHorizontalFrame.new(self)
32
+ @quit_btn = FXButton.new(@control_frame, "Quit")
33
+ @refresh_btn = FXButton.new(@control_frame, "Refresh")
34
+ @post_btn = FXButton.new(@control_frame, "Post")
35
+ FXHorizontalSeparator.new(@control_frame)
36
+ @length_lbl = FXLabel.new(@control_frame, TWEET_LENGTH.to_s)
37
+ @twitter_input = FXTextField.new(self, 80,
38
+ :opts => LAYOUT_FILL_X | TEXTFIELD_ENTER_ONLY,
39
+ :width => 450)
40
+ @status_line = FXStatusLine.new(self)
41
+ @status_line.normalText = "fxtwitter"
42
+
43
+ @post_btn.connect(SEL_COMMAND) do |sender, selector, data|
44
+ post_tweet()
45
+ end
46
+
47
+ @quit_btn.connect(SEL_COMMAND) do |sender, selecter, data|
48
+ quit_application()
49
+ end
50
+
51
+ @refresh_btn.connect(SEL_COMMAND) do |sender, selector, data|
52
+ update_tweets()
53
+ end
54
+
55
+ @twitter_input.connect(SEL_CHANGED) do |sender, selector, data|
56
+ @length_lbl.text = (TWEET_LENGTH - data.length).to_s
57
+ end
58
+
59
+ @twitter_input.connect(SEL_COMMAND) do |sender, selector, data|
60
+ post_tweet()
61
+ end
62
+
63
+ # Set up text styles for the twitter display
64
+ name_style = FXHiliteStyle.from_text(@tweet_display)
65
+ name_style.style = FXText::STYLE_BOLD
66
+ time_style = FXHiliteStyle.from_text(@tweet_display)
67
+ time_style.normalForeColor = FXColor::MidnightBlue
68
+ @tweet_display.styled = true
69
+ @tweet_display.hiliteStyles = [ name_style, time_style ]
70
+
71
+ # TODO: Replace global constant with config and/or user input.
72
+ @tweets_updated_at = nil
73
+ @tweets = []
74
+ end
75
+
76
+ # Opens a validated connection to the Twitter service.
77
+ def connect_to_twitter(login, password)
78
+ @status_line.text = "Connecting #{login} to Twitter"
79
+ return Twitter::Client.new(:login => login, :password => password)
80
+ end
81
+
82
+ # Part of the GUI construction code
83
+ def create()
84
+ super
85
+ show(PLACEMENT_SCREEN)
86
+ setup_twitter()
87
+ end
88
+
89
+ # Submit user text from twitter_input
90
+ def post_tweet()
91
+ tweet_text = @twitter_input.text
92
+ if tweet_text.length > 0 then
93
+ if tweet_text.length <= TWEET_LENGTH then
94
+ @status_line.text = "Posting Tweet..."
95
+ status = Twitter::Status.create(:text => tweet_text,
96
+ :client => @twitter)
97
+ @twitter_input.text = ""
98
+ @length_lbl.text = TWEET_LENGTH.to_s
99
+ else
100
+ message = "Your Tweet must have #{TWEET_LENGTH} or less characters"
101
+ FXMessageBox.warning(self, MBOX_OK, "Tweet too long!", message)
102
+ end
103
+ end
104
+ end
105
+
106
+ # Perform any needed cleanup and exit
107
+ def quit_application()
108
+ exit
109
+ end
110
+
111
+ def setup_twitter()
112
+ if @username and @password then
113
+ @twitter = connect_to_twitter(@username, @password)
114
+ update_tweets()
115
+
116
+ # Check for new Tweets every minute
117
+ timeout_duration = 60 * 1000
118
+ @refresh_timeout = app.addTimeout(timeout_duration, :repeat => true) do |sender, selector, data|
119
+ update_tweets()
120
+ end
121
+ else
122
+ # TODO: Login view
123
+ raise "Username and password required. fxtwitter --help for usage"
124
+ end
125
+ end
126
+
127
+ def update_tweets()
128
+ this_load = Time.now
129
+ @status_line.text = "#{this_load}: Updating Tweets..."
130
+ begin
131
+ if @tweets and @tweets_updated_at then
132
+ tweets = @twitter.timeline_for(:friends, :since => @tweets_updated_at)
133
+ @tweets_updated_at = Time.now
134
+ else
135
+ tweets = @twitter.timeline_for(:friends)
136
+ @tweets_updated_at = this_load
137
+ end
138
+ rescue Twitter::RESTError => e
139
+ if e.message == "Not Modified" then
140
+ @status_line.normalText = "#{this_load}: No new Tweets"
141
+ return
142
+ else
143
+ raise e
144
+ end
145
+ end
146
+ @tweets = tweets
147
+ @tweets_updated_at = this_load
148
+ @status_line.normalText = "#{@tweets_updated_at}: #{@tweets.length} new Tweets"
149
+
150
+ # Now that we have new Tweets, display them.
151
+ @tweets.reverse.each do |tweet|
152
+ created_at = tweet.created_at.strftime("%I:%M %p")
153
+ screen_name = CGI::unescapeHTML(tweet.user.screen_name)
154
+ text = ": #{CGI::unescapeHTML(tweet.text)} -- "
155
+ @tweet_display.appendStyledText(screen_name, 1)
156
+ @tweet_display.appendText(text)
157
+ @tweet_display.appendStyledText(created_at, 2)
158
+ @tweet_display.appendStyledText("\n")
159
+ @tweet_display.makePositionVisible(@tweet_display.cursorPos)
160
+ end
161
+ end
162
+
163
+ end
164
+
165
+ # Runs the fxtwitter application.
166
+ def FxTwitter.main()
167
+ require 'optparse'
168
+ login = nil
169
+ password = nil
170
+ opts = OptionParser.new
171
+ opts.on("-u", "--user USERNAME", "Twitter account name", String) { |val| login = val }
172
+ opts.on("-p", "--password PASSWORD", "Twitter account password", String) { |val| password = val }
173
+ opts.on("-h", "--help", "Show usage") { |val| puts opts.to_s; exit }
174
+ opts.parse(ARGV)
175
+
176
+ unless login and password
177
+ puts "Username and password required in this version of fxtwitter"
178
+ print opts.to_s
179
+ exit
180
+ end
181
+
182
+ application = FXApp.new
183
+ main_window = TwitterWindow.new(application, login, password)
184
+ application.create()
185
+ application.run()
186
+ end
187
+ end
@@ -0,0 +1,3 @@
1
+ # No tests yet!
2
+ # (How *do* I test a GUI?)
3
+
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fxtwitter
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Brian Wisti
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-03-16 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: fxruby
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: "0"
23
+ version:
24
+ - !ruby/object:Gem::Dependency
25
+ name: twitter4r
26
+ version_requirement:
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - - ">="
30
+ - !ruby/object:Gem::Version
31
+ version: "0"
32
+ version:
33
+ - !ruby/object:Gem::Dependency
34
+ name: hoe
35
+ version_requirement:
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 1.5.1
41
+ version:
42
+ description: fxtwitter is a GUI client for the Twitter <http://twitter.com> system. It provides a simple interface comparable to many popular instant messaging chat clients.
43
+ email:
44
+ - brianwisti@rubyforge.org
45
+ executables:
46
+ - fxtwitter
47
+ extensions: []
48
+
49
+ extra_rdoc_files:
50
+ - History.txt
51
+ - Manifest.txt
52
+ - README.txt
53
+ files:
54
+ - History.txt
55
+ - Manifest.txt
56
+ - README.txt
57
+ - Rakefile
58
+ - bin/fxtwitter
59
+ - lib/fxtwitter.rb
60
+ - test/test_fxtwitter.rb
61
+ has_rdoc: true
62
+ homepage: http://projects.rubyforge.org/fxtwitte
63
+ post_install_message:
64
+ rdoc_options:
65
+ - --main
66
+ - README.txt
67
+ require_paths:
68
+ - lib
69
+ required_ruby_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: "0"
74
+ version:
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: "0"
80
+ version:
81
+ requirements: []
82
+
83
+ rubyforge_project: fxtwitter
84
+ rubygems_version: 1.0.1
85
+ signing_key:
86
+ specification_version: 2
87
+ summary: fxtwitter is a GUI client for the Twitter <http://twitter.com> system
88
+ test_files:
89
+ - test/test_fxtwitter.rb