twitterpunch 0.0.3 → 0.0.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 96c566d4bdc10313e9efc77b92c9cfa407048617
4
- data.tar.gz: 59b7a93bd2cdda89c79cc1b99f2811a77b1230e4
3
+ metadata.gz: c881f24bd1e7cc981175e5f5fb52f80a7725e12f
4
+ data.tar.gz: 7516403fe3be89a85cf8ac0a11427857a28119a7
5
5
  SHA512:
6
- metadata.gz: 17cfa29c54696a7dcdecb8ee77c03b3cdbd2c2c0d30479b77abce4722a2f519159939e3d37037da74ea6dda61f235c18fb33e4a0e7261bfbf11278c733e8cf29
7
- data.tar.gz: fc1a39f9a4a93b7896510d48242f3ad968a7ccf8721ee3d966195c0286ab470c706b87fa7b84ffc266d01114d71a7ba5e53feef3bc838e07cb67b58f9ef04e71
6
+ metadata.gz: 2e2a4303a64a59f3cee1c582b74706fdbff6f7095ea60b3b4adcbc2c3c85c404f384f07d1b94e7c9abaed2c6ee340f2dcd1f8292ccbc67602b7f19e58110ebe1
7
+ data.tar.gz: 6c147d09131b4393231a97d531fe029fa3101299aff4e0dc154c3223c49b9407f684020559bd1102d1f0ebbb48f7faa8a111661da831ad1045d96197b7c1b420
data/README.md CHANGED
@@ -17,20 +17,20 @@ Configure the program via the `~/.twitterpunch.yaml` YAML file. This file should
17
17
  look similar to the example below.
18
18
 
19
19
  ---
20
- :twitter:
20
+ :twitter: # twitter configuration
21
21
  :consumer_key: <consumer key>
22
22
  :consumer_secret: <consumer secret>
23
23
  :access_token: <access token>
24
24
  :access_token_secret: <access secret>
25
- :messages:
26
- - Hello there
25
+ :messages: # list of messages to attach
26
+ - Hello there # to outgoing tweets
27
27
  - I'm a posting fool
28
28
  - minimally viable product
29
- :hashtag: BestHalloweenPartyEver
30
- :handle: FassFord
31
- :photodir: ~/Pictures/twitterpunch/
32
- :logfile: /Users/ben/.twitterpunch.log
33
- :sendsound: /System/Library/PrivateFrameworks/ToneLibrary.framework/Versions/A/Resources/AlertTones/tweet_sent.caf
29
+ :hashtag: Twitterpunch # The hashtag to post and listen to
30
+ :photodir: ~/Pictures/twitterpunch/ # Where to save downloaded images
31
+ :logfile: ~/.twitterpunch.log # Where to save logs
32
+ :viewer: # Use the built-in slideshow viewer
33
+ :count: 5 # How many images to have onscreen at once
34
34
 
35
35
  A skeleton configuration file, with access tokens from Twitter, can be generated
36
36
  by running the program with the `--genconfig` flag.
@@ -71,14 +71,18 @@ multiple files at once.
71
71
 
72
72
  ### Viewing the Twitter stream
73
73
 
74
- Currently Twitterpunch doesn't display photos directly. It simply downloads them
75
- and stuffs them into the configured `:photodir`. Twitterpunch will run on OS X or
76
- Windows equally well. Simply configure it on the computer that will act as the
77
- Twitter display and then run in streaming mode. Tweets that come from any other
78
- user will be spoken aloud.
74
+ Twitterpunch will run on OS X or Windows equally well. Simply configure it on the
75
+ computer that will act as the Twitter display and then run in streaming mode.
76
+ All images tweeted to the configured hashtag will be displayed in the slideshow
77
+ and tweets that come from any other user will also be spoken aloud.
79
78
 
80
79
  [ben@ganymede] ~ $ twitterpunch --stream
81
80
 
81
+ If you don't want to use the built-in slideshow viewer, you can disable it by
82
+ removing the `:viewer` key from your `~/.twitterpunch.yaml` config file. Twitterpunch
83
+ will then simply download the tweeted images and save them into the `:photodir`
84
+ directory. You can then use anything you like to view them.
85
+
82
86
  There are currently two decent viewing options I am aware of.
83
87
 
84
88
  * Windows background image:
@@ -98,7 +102,7 @@ Limitations
98
102
  ===========
99
103
 
100
104
  * It currently requires manual setup for Folder Actions.
101
- * It currently requires an external viewer, such as a screensaver.
105
+ * Rubygame is kind of a pain to set up.
102
106
 
103
107
 
104
108
  Contact
data/bin/twitterpunch CHANGED
@@ -66,11 +66,14 @@ when :stream
66
66
  require 'twitterpunch/streamer'
67
67
  require 'twitterpunch/viewer'
68
68
 
69
- statefile = File.expand_path('~/.twitterpunch.state')
70
- config[:state] = YAML.load_file(statefile) rescue {}
69
+ statefile = File.expand_path('~/.twitterpunch.state')
70
+ viewer = Twitterpunch::Viewer.new(config)
71
+
72
+ config[:state] = YAML.load_file(statefile) rescue {}
73
+ config[:display] = viewer
71
74
 
72
75
  Twitterpunch::Streamer.new(config).thread
73
- Twitterpunch::Viewer.new(config)
76
+ viewer.run
74
77
 
75
78
  File.open(statefile, 'w') {|f| f.write(config[:state].to_yaml) }
76
79
 
@@ -85,7 +88,8 @@ when :view
85
88
  statefile = File.expand_path('~/.twitterpunch.state')
86
89
  config[:state] = YAML.load_file(statefile) rescue {}
87
90
 
88
- client = Twitterpunch::Viewer.new(config)
91
+ viewer = Twitterpunch::Viewer.new(config)
92
+ viewer.run
89
93
 
90
94
  when :configure
91
95
  require 'twitterpunch/configuration'
data/lib/twitterpunch.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Twitterpunch
2
- VERSION = '0.0.3'
2
+ VERSION = '0.0.4'
3
3
  end
@@ -59,10 +59,9 @@ module Twitterpunch
59
59
  :viewer => {
60
60
  :count => 5,
61
61
  },
62
- :hashtag => "BestHalloweenPartyEver",
63
- :handle => "fassford",
62
+ :hashtag => "Twitterpunch",
64
63
  :photodir => "~/Pictures/twitterpunch/",
65
- :logfile => '/var/log/twitterpunch',
64
+ :logfile => '~/.twitterpunch.log',
66
65
  }
67
66
  end
68
67
  end
@@ -7,7 +7,7 @@ module Twitterpunch
7
7
  class Logger
8
8
  def initialize(config)
9
9
  @options = config
10
- @logger = ::Logger.new(config[:logfile])
10
+ @logger = ::Logger.new(File.expand_path(config[:logfile]))
11
11
 
12
12
  @logger.level = config[:debug] ? ::Logger::DEBUG : ::Logger::INFO
13
13
  end
@@ -6,34 +6,55 @@ module Twitterpunch
6
6
  include Rubygame
7
7
  include Sprites::Sprite
8
8
 
9
- def initialize(dimensions, image, text)
9
+ def initialize(dimensions, image, text, pop=false)
10
10
  # Invoking the base class constructor is important and yet easy to forget:
11
11
  super()
12
12
 
13
13
  @dimensions = dimensions
14
+ @popped = pop
15
+ @text = text
16
+ @original = Surface.load(image)
14
17
 
15
- @rate = rand(35..150)
16
- @zoom = rand(50..100) / 100.0
17
-
18
- # @image and @rect are expected by the Rubygame sprite code
19
- @image = Surface.load(image).zoom(@zoom)
18
+ if pop
19
+ @image = @original
20
+ @start = Time.now
21
+ @stale = 10
22
+ else
23
+ @rate = rand(35..150)
24
+ @zoom = rand(50..100) / 100.0
25
+ @image = @original.zoom(@zoom)
26
+ end
20
27
 
21
28
  max_width = dimensions[0] * 0.75
22
29
  if @image.width > max_width
23
- @image = @image.zoom(max_width/@image.width)
30
+ factor = max_width/@image.width
31
+ @original = @original.zoom(factor)
32
+ @image = @image.zoom(factor)
33
+ end
34
+
35
+ if pop
36
+ @left = (dimensions[0] - @image.width) / 2
37
+ @top = (dimensions[1] - @image.height) / 2
38
+ else
39
+ @left = (dimensions[0] - @image.width ) * rand
40
+ @top = 0 - @image.height
24
41
  end
25
42
 
26
- @top = 0 - @image.height
27
- @left = (dimensions[0] - @image.width ) * rand
28
43
  @rect = @image.make_rect
29
44
 
30
- if text
31
- @text = $font.render_utf8(text, true, Color[:black], Color[:gray])
32
- @text.alpha = 150
45
+ render_text
46
+ end
47
+
48
+ def render_text
49
+ if @text
50
+ text = $font.render_utf8(@text, true, Color[:black], Color[:gray])
51
+
52
+ # for some reason, windows doesn't deal with this properly
53
+ text.alpha = 150 unless RUBY_PLATFORM =~ /mingw|cygwin/
33
54
 
34
55
  # Determine the dimensions in pixels of the area used to render the text. The
35
56
  # "topleft" of the returned rectangle is at [ 0, 0]
36
- rt = @text.make_rect
57
+ rt = text.make_rect
37
58
 
38
59
  # Re-use the "topleft" of the rectangle to indicate where the text should
39
60
  # appear on screen ( lower left corner )
@@ -41,16 +62,34 @@ module Twitterpunch
41
62
  rt.topleft = [ 0, @image.height - rt.height]
42
63
 
43
64
  # Copy the pixels of the rendered text to the image
44
- @text.blit(@image, rt)
65
+ text.blit(@image, rt)
45
66
  end
46
67
  end
47
68
 
48
- # Animate this object. "seconds_passed" contains the number of ( real-world)
69
+ # Animate this object. "seconds_passed" contains the number of real-world
49
70
  # seconds that have passed since the last time this object was updated and is
50
- # therefore useful for working out how far the object should move ( which
71
+ # therefore useful for working out how far the object should move (which
51
72
  # should be independent of the frame rate)
52
73
  def update(seconds_passed)
53
- @top += seconds_passed * @rate
74
+ if @popped
75
+ elapsed = (Time.now - @start).to_f
76
+
77
+ if elapsed < 1
78
+ scale = 1 + damped_sin(elapsed, 4, 0.05)
79
+
80
+ @image = @original.zoom(scale)
81
+ @top *= scale
82
+ @left *= scale
83
+
84
+ # We changed image size, so rebuild the rect and draw new text
85
+ @rect = @image.make_rect
86
+ render_text
87
+ elsif elapsed > @stale
88
+ @image.alpha -= 5
89
+ end
90
+ else
91
+ @top += seconds_passed * @rate
92
+ end
54
93
  @rect.topleft = [ @left, @top ]
55
94
  end
56
95
 
@@ -59,7 +98,19 @@ module Twitterpunch
59
98
  end
60
99
 
61
100
  def visible
62
- @top < @dimensions[1]
101
+ if @popped
102
+ @image.alpha > 0
103
+ else
104
+ @top < @dimensions[1]
105
+ end
106
+ end
107
+
108
+ def damped_sin(input, cycles = 4, scale = 1)
109
+ Math.sin(input * cycles * Math::PI) * (1 - input) * scale
110
+ end
111
+
112
+ def popped?
113
+ return @popped
63
114
  end
64
115
  end
65
116
  end
@@ -12,6 +12,8 @@ module Twitterpunch
12
12
  @client = Twitter::Streaming::Client.new(config[:twitter])
13
13
  @logger = Twitterpunch::Logger.new(config)
14
14
  @output = File.expand_path(config[:photodir])
15
+ @handle = Twitter::REST::Client.new(config[:twitter]).current_user.screen_name
16
+ @viewer = config[:display]
15
17
 
16
18
  FileUtils.mkdir_p(@output) unless File.directory?(@output)
17
19
  end
@@ -31,18 +33,6 @@ module Twitterpunch
31
33
 
32
34
  content = tweet.text.gsub(/ http\S*/,'').gsub(/#\S*/,'')
33
35
 
34
-
35
- unless tweet.user.screen_name == @config[:handle]
36
- message = "#{tweet.user.name} says #{content}"
37
-
38
- case RUBY_PLATFORM
39
- when /mingw|cygwin/
40
- system('cscript', "#{@config[:resources]}/say.vbs", message)
41
- when /darwin/
42
- system('say', message)
43
- end
44
- end
45
-
46
36
  if tweet.media?
47
37
  uri = tweet.media.first.media_uri
48
38
 
@@ -56,16 +46,33 @@ module Twitterpunch
56
46
  file.write(response.body)
57
47
  end
58
48
 
59
- unless tweet.user.screen_name == @config[:handle]
49
+ unless tweet.user.screen_name == @handle
60
50
  @config[:state][image] = content
61
51
  end
62
52
 
63
- # OS X screensaver doesn't reload images dynamically. This kinda sucks.
64
- if RUBY_PLATFORM =~ /darwin/ and not @config.has_key? :viewer
65
- system('osascript', '-e', 'tell application "System Events" to stop current screen saver')
66
- system('osascript', '-e', 'tell application "System Events" to start current screen saver')
53
+ if @viewer
54
+ @viewer.pop(image, content)
55
+ else
56
+ # OS X screensaver doesn't reload images dynamically. This kinda sucks.
57
+ if RUBY_PLATFORM =~ /darwin/ and system('pgrep ScreenSaverEngine >/dev/null')
58
+ system('osascript', '-e', 'tell application "System Events" to stop current screen saver')
59
+ system('osascript', '-e', 'tell application "System Events" to start current screen saver')
60
+ end
67
61
  end
62
+
68
63
  end
64
+
65
+ unless tweet.user.screen_name == @handle
66
+ message = "#{tweet.user.name} says #{content}"
67
+
68
+ case RUBY_PLATFORM
69
+ when /mingw|cygwin/
70
+ system('cscript', "#{@config[:resources]}/say.vbs", message)
71
+ when /darwin/
72
+ system('say', message)
73
+ end
74
+ end
75
+
69
76
  end
70
77
  end
71
78
  rescue Interrupt => e
@@ -9,18 +9,19 @@ module Twitterpunch
9
9
 
10
10
  def initialize(config)
11
11
  @config = config
12
- @state = YAML.load_file(File.expand_path('~/.twitterpunch.state')) rescue {}
13
12
  srand
13
+ end
14
14
 
15
+ def run
15
16
  if @config.has_key? :viewer
16
- run
17
+ display
17
18
  else
18
19
  puts 'Press enter to exit'
19
20
  STDIN.gets
20
21
  end
21
22
  end
22
23
 
23
- def run
24
+ def display
24
25
  onscreen = @config[:viewer][:count] || 5
25
26
 
26
27
  # Set up the TrueType Font module
@@ -30,9 +31,9 @@ module Twitterpunch
30
31
 
31
32
  #@screen = Screen.open [ 640, 480]
32
33
  default_depth = 0
33
- maximum_resolution = Screen.get_resolution
34
+ @maximum_resolution = Screen.get_resolution
34
35
 
35
- screen = Screen.open(maximum_resolution, default_depth, [ HWSURFACE, DOUBLEBUF, FULLSCREEN])
36
+ screen = Screen.open(@maximum_resolution, default_depth, [ HWSURFACE, DOUBLEBUF, FULLSCREEN])
36
37
 
37
38
  screen.show_cursor = false
38
39
 
@@ -45,15 +46,15 @@ module Twitterpunch
45
46
 
46
47
  # Create a new group of sprites so that all sprites in the group may be updated
47
48
  # or drawn with a single method invocation.
48
- sprites = Sprites::Group.new
49
- Sprites::UpdateGroup.extend_object(sprites)
49
+ @sprites = Sprites::Group.new
50
+ Sprites::UpdateGroup.extend_object(@sprites)
50
51
  onscreen.times do
51
- sprites << Twitterpunch::Sprite.new(maximum_resolution, *next_image)
52
+ @sprites << Twitterpunch::Sprite.new(@maximum_resolution, *next_image)
52
53
  end
53
54
 
54
55
  #@background = Surface.load("background.png").zoom_to(maximum_resolution[0], maximum_resolution[1])
55
56
  # Create a background image and copy it to the screen. With no image, it's just black.
56
- background = Surface.new(maximum_resolution)
57
+ background = Surface.new(@maximum_resolution)
57
58
  background.blit(screen, [ 0, 0])
58
59
 
59
60
  event_queue = EventQueue.new
@@ -71,26 +72,37 @@ module Twitterpunch
71
72
  end
72
73
 
73
74
  # remove all sprites who've gone out of sight
74
- sprites.reject { |sprite| sprite.visible }.each do |sprite|
75
+ @sprites.reject { |sprite| sprite.visible }.each do |sprite|
76
+ sprite.undraw(screen, background)
75
77
  sprite.kill
76
- sprites << Twitterpunch::Sprite.new(maximum_resolution, *next_image)
78
+ next if sprite.popped?
79
+
80
+ @sprites << Twitterpunch::Sprite.new(@maximum_resolution, *next_image)
77
81
  end
78
82
 
79
83
  # "undraw" all of the sprites by drawing the background image at their
80
84
  # current location ( before their location has been changed by the animation)
81
- sprites.undraw(screen, background)
85
+ @sprites.undraw(screen, background)
82
86
 
83
87
  # Give all of the sprites an opportunity to move themselves to a new location
84
- sprites.update(seconds_passed)
88
+ @sprites.update(seconds_passed)
85
89
 
86
90
  # Draw all of the sprites
87
- sprites.draw(screen)
91
+ @sprites.draw(screen)
92
+
93
+ # Then redraw the popped sprite to ensure it's on top
94
+ @sprites.select { |sprite| sprite.popped? }.each { |popped| popped.draw(screen) }
88
95
 
89
96
  screen.flip
90
97
  end
91
98
 
92
99
  end
93
100
 
101
+ def pop(image, text)
102
+ path = File.expand_path("#{@config[:photodir]}/#{image}")
103
+ @sprites << Twitterpunch::Sprite.new(@maximum_resolution, path, text, true)
104
+ end
105
+
94
106
  def next_image
95
107
  image = Dir.glob(File.expand_path("#{@config[:photodir]}/*")).sample
96
108
  text = @config[:state][File.basename(image)]
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: twitterpunch
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Ford
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-10-30 00:00:00.000000000 Z
11
+ date: 2014-11-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: twitter
@@ -74,15 +74,19 @@ description: "Twitterpunch\n===============\n\nTwitterpunch is designed to work
74
74
  them to a specified directory. If\nthe tweet came from another user, Twitterpunch
75
75
  will speak it aloud.\n\nConfiguration\n===========\n\nConfigure the program via
76
76
  the `~/.twitterpunch.yaml` YAML file. This file should\nlook similar to the example
77
- below.\n\n ---\n :twitter:\n :consumer_key: <consumer key>\n :consumer_secret:
78
- <consumer secret>\n :access_token: <access token>\n :access_token_secret:
79
- <access secret>\n :messages:\n - Hello there\n - I'm a posting fool\n -
80
- minimally viable product\n :hashtag: BestHalloweenPartyEver\n :handle: FassFord\n
81
- \ :photodir: ~/Pictures/twitterpunch/\n :logfile: /Users/ben/.twitterpunch.log\n
82
- \ :sendsound: /System/Library/PrivateFrameworks/ToneLibrary.framework/Versions/A/Resources/AlertTones/tweet_sent.caf\n\nA
83
- skeleton configuration file, with access tokens from Twitter, can be generated\nby
84
- running the program with the `--genconfig` flag.\n\nUsage \n==========\n\n### Using
85
- OS X PhotoBooth\n\n1. Start PhotoBooth at least once to generate its library.\n1.
77
+ below.\n\n ---\n :twitter: # twitter configuration\n
78
+ \ :consumer_key: <consumer key>\n :consumer_secret: <consumer secret>\n
79
+ \ :access_token: <access token>\n :access_token_secret: <access secret>\n
80
+ \ :messages: # list of messages to attach\n -
81
+ Hello there # to outgoing tweets\n - I'm a posting
82
+ fool\n - minimally viable product\n :hashtag: Twitterpunch #
83
+ The hashtag to post and listen to\n :photodir: ~/Pictures/twitterpunch/ #
84
+ Where to save downloaded images\n :logfile: ~/.twitterpunch.log # Where
85
+ to save logs\n :viewer: # Use the built-in slideshow
86
+ viewer\n :count: 5 # How many images to have onscreen
87
+ at once\n\nA skeleton configuration file, with access tokens from Twitter, can be
88
+ generated\nby running the program with the `--genconfig` flag.\n\nUsage \n==========\n\n###
89
+ Using OS X PhotoBooth\n\n1. Start PhotoBooth at least once to generate its library.\n1.
86
90
  Install the Twitterpunch Folder Action\n * `twitterpunch --install`\n * It
87
91
  may claim that it could not be attached, fear not.\n1. Profit!\n * _and by that,
88
92
  I mean take some shots with PhotoBooth!_\n\n#### Troubleshooting.\n\n1. Make sure
@@ -97,24 +101,27 @@ description: "Twitterpunch\n===============\n\nTwitterpunch is designed to work
97
101
  the program you are using for your photo shoot to call Twitterpunch\neach time it
98
102
  snaps a photo. Pass the name of the new photo as a command line\nargument. Alternatively,
99
103
  you could batch them, as Twitterpunch can accept\nmultiple files at once.\n\n [ben@ganymede]
100
- ~ $ twitterpunch photo.jpg\n\n### Viewing the Twitter stream\n\nCurrently Twitterpunch
101
- doesn't display photos directly. It simply downloads them\nand stuffs them into
102
- the configured `:photodir`. Twitterpunch will run on OS X or\nWindows equally well.
103
- Simply configure it on the computer that will act as the \nTwitter display and then
104
- run in streaming mode. Tweets that come from any other\nuser will be spoken aloud.\n\n
105
- \ [ben@ganymede] ~ $ twitterpunch --stream\n\nThere are currently two decent viewing
106
- options I am aware of.\n\n* Windows background image:\n * Configure the Windows
107
- background to randomly cycle through photos in a directory.\n * Hide desktop
108
- icons.\n * Hide the taskbar.\n * Disable screensaver and power savings.\n
109
- \ * Drawbacks: You're using Windows and you have to install Ruby & RubyGems manually.\n*
110
- OS X screensaver:\n * Choose one of the sexy screensavers and configure it to
111
- show photos from the `:photodir`\n * Set screensaver to a super short timeout.\n
112
- \ * Disable power savings.\n * Drawbacks: The screensaver doesn't reload dynamically,
113
- so I have to kick it\n and you'll see it reloading each time a new tweet comes
114
- in.\n\nLimitations\n===========\n\n* It currently requires manual setup for Folder
115
- Actions.\n* It currently requires an external viewer, such as a screensaver.\n\n\nContact\n=======\n\n*
116
- Author: Ben Ford\n* Email: binford2k@gmail.com\n* Twitter: @binford2k\n* IRC (Freenode):
117
- binford2k\n"
104
+ ~ $ twitterpunch photo.jpg\n\n### Viewing the Twitter stream\n\nTwitterpunch will
105
+ run on OS X or Windows equally well. Simply configure it on the\ncomputer that will
106
+ act as the Twitter display and then run in streaming mode.\nAll images tweeted to
107
+ the configured hashtag will be displayed in the slideshow\nand tweets that come
108
+ from any other user will also be spoken aloud.\n\n [ben@ganymede] ~ $ twitterpunch
109
+ --stream\n\nIf you don't want to use the built-in slideshow viewer, you can disable
110
+ it by\nremoving the `:viewer` key from your `~/.twitterpunch.yaml` config file.
111
+ Twitterpunch\nwill then simply download the tweeted images and save them into the
112
+ `:photodir`\ndirectory. You can then use anything you like to view them.\n\nThere
113
+ are currently two decent viewing options I am aware of.\n\n* Windows background
114
+ image:\n * Configure the Windows background to randomly cycle through photos
115
+ in a directory.\n * Hide desktop icons.\n * Hide the taskbar.\n * Disable
116
+ screensaver and power savings.\n * Drawbacks: You're using Windows and you have
117
+ to install Ruby & RubyGems manually.\n* OS X screensaver:\n * Choose one of the
118
+ sexy screensavers and configure it to show photos from the `:photodir`\n * Set
119
+ screensaver to a super short timeout.\n * Disable power savings.\n * Drawbacks:
120
+ The screensaver doesn't reload dynamically, so I have to kick it\n and you'll
121
+ see it reloading each time a new tweet comes in.\n\nLimitations\n===========\n\n*
122
+ It currently requires manual setup for Folder Actions.\n* Rubygame is kind of a
123
+ pain to set up.\n\n\nContact\n=======\n\n* Author: Ben Ford\n* Email: binford2k@gmail.com\n*
124
+ Twitter: @binford2k\n* IRC (Freenode): binford2k\n"
118
125
  email: binford2k@gmail.com
119
126
  executables:
120
127
  - twitterpunch