Skip to content

Instantly share code, notes, and snippets.

@no6v
Created January 21, 2012 07:17
Show Gist options
  • Save no6v/1651877 to your computer and use it in GitHub Desktop.
Save no6v/1651877 to your computer and use it in GitHub Desktop.
diff --git a/lib/earthquake.rb b/lib/earthquake.rb
index be11649..328df67 100644
--- a/lib/earthquake.rb
+++ b/lib/earthquake.rb
@@ -27,4 +27,5 @@ Encoding.default_external = Encoding.find('UTF-8')
help
commands
id_var
+ item
).each { |name| require_dependency File.expand_path("../earthquake/#{name}", __FILE__) }
diff --git a/lib/earthquake/item.rb b/lib/earthquake/item.rb
new file mode 100644
index 0000000..0a144e4
--- /dev/null
+++ b/lib/earthquake/item.rb
@@ -0,0 +1,243 @@
+module Earthquake
+ class Item
+ [
+ :config,
+ :color_of,
+ :id2var,
+ ].each do |m|
+ delegate m, :to => Earthquake
+ private m
+ end
+
+ def initialize(item)
+ @item = item
+ end
+
+ def to_status
+ text = body.u
+ if config[:raw_text]
+ text.prepend("\n")
+ else
+ text.gsub!(/\s+/, " ")
+ end
+ text = highlight(text)
+ [prefix, screen_name, text, protected_mark, info].compact.join(" ")
+ end
+
+ def inspect
+ super.split.first << ?>
+ end
+
+ protected
+
+ def body
+ if truncated? and retweet?
+ item = Item.new(retweeted_status)
+ "RT #{item.screen_name(?@)} #{item.body}"
+ else
+ colored_text
+ end
+ end
+
+ def screen_name(prefix = "")
+ screen_name = @item["user"]["screen_name"]
+ "#{prefix}#{screen_name}".c(color_of(screen_name)) + ":"
+ end
+
+ private
+
+ def protected_mark
+ "[P]".c(:notice) if protected?
+ end
+
+ def protected?
+ @item["user"]["protected"]
+ end
+
+ def highlight(text)
+ if highlights = @item["_highlights"]
+ highlights.each do |h|
+ color = config[:color][:highlight].nil? ? color_of(h).to_i + 10 : :highlight
+ text = text.coloring(/#{h}/i, color)
+ end
+ end
+ text
+ end
+
+ def info
+ info = []
+ info << (reply_info || retweet_info)
+ info << time_info unless config[:hide_time]
+ info << source_info unless config[:hide_app_name]
+ info.compact.join(" - ").c(:info)
+ end
+
+ def reply_info
+ if in_reply_to_status_id_str = @item["in_reply_to_status_id_str"]
+ "(reply to #{id2var(in_reply_to_status_id_str)})"
+ end
+ end
+
+ def retweet_info
+ if retweet?
+ "(retweet of #{id2var(retweeted_status["id_str"])})"
+ end
+ end
+
+ def time_info
+ if created_at = @item["created_at"]
+ Time.parse(created_at).strftime(config[:time_format])
+ end
+ end
+
+ def source_info
+ if source = @item["source"]
+ source.u =~ />(.*)</ ? $1 : 'web'
+ end
+ end
+
+ def prefix
+ mark + "[#{id2var(status_id)}]".c(:info)
+ end
+
+ def mark
+ @item["_mark"] || ""
+ end
+
+ def status_id
+ @item["id_str"]
+ end
+
+ def truncated?
+ @item["truncated"]
+ end
+
+ def retweet?
+ @item.key?("retweeted_status")
+ end
+
+ def retweeted_status
+ @item["retweeted_status"]
+ end
+
+ def colored_text
+ Entity.apply(@item["text"], @item["entities"])
+ end
+
+ module Entity
+ class << self
+ def apply(text, item_entities)
+ text = text.dup
+ parse(item_entities).inject(0) do |offset, entity|
+ offset + entity.apply(text, offset)
+ end
+ text
+ end
+
+ private
+
+ def parse(item_entities)
+ item_entities.flat_map{|type, entities|
+ entities.map{|entity|
+ klass = type.classify
+ const_get(klass).new(entity) if const_defined?(klass)
+ }.compact
+ }.sort_by!(&:position)
+ end
+ end
+
+ class Base
+ [
+ :config,
+ :color_of,
+ ].each do |m|
+ delegate m, :to => Earthquake
+ private m
+ end
+
+ def initialize(entity)
+ @entity = entity
+ @first, @last = entity["indices"]
+ end
+
+ def position
+ @first
+ end
+
+ def apply(text, offset)
+ colored_text = coloring
+ text[range(offset)] = colored_text
+ colored_text.size - size
+ end
+
+ private
+
+ def size
+ @last - @first
+ end
+
+ def body
+ @entity[key]
+ end
+
+ def key
+ raise NotImplementedError, "need to define `key'"
+ end
+
+ def string
+ body
+ end
+
+ def range(offset)
+ (@first + offset) ... (@last + offset)
+ end
+
+ def coloring
+ string.c(color_of(string))
+ end
+ end
+
+ class UrlBase < Base
+ private
+
+ def string
+ config[:expand_url] && @entity["expanded_url"] || @entity["url"]
+ end
+
+ def coloring
+ string.c(:url)
+ end
+ end
+
+ class Url < UrlBase
+ end
+
+ class Medium < UrlBase
+ end
+
+ class Hashtag < Base
+ private
+
+ def key
+ "text"
+ end
+
+ def string
+ "#" + body
+ end
+ end
+
+ class UserMention < Base
+ private
+
+ def key
+ "screen_name"
+ end
+
+ def string
+ "@" + body
+ end
+ end
+ end
+ end
+end
diff --git a/lib/earthquake/output.rb b/lib/earthquake/output.rb
index a5a19dc..ad866f8 100644
--- a/lib/earthquake/output.rb
+++ b/lib/earthquake/output.rb
@@ -85,56 +85,8 @@ module Earthquake
output :tweet do |item|
next unless item["text"]
- info = []
- if item["in_reply_to_status_id"]
- info << "(reply to #{id2var(item["in_reply_to_status_id"])})"
- elsif item["retweeted_status"]
- info << "(retweet of #{id2var(item["retweeted_status"]["id"])})"
- end
- if !config[:hide_time] && item["created_at"]
- info << Time.parse(item["created_at"]).strftime(config[:time_format])
- end
- if !config[:hide_app_name] && item["source"]
- info << (item["source"].u =~ />(.*)</ ? $1 : 'web')
- end
-
- id = id2var(item["id"])
-
- text = (item["retweeted_status"] && item["truncated"] ? "RT @#{item["retweeted_status"]["user"]["screen_name"]}: #{item["retweeted_status"]["text"]}" : item["text"]).u
- text.gsub!(/\s+/, ' ') unless config[:raw_text]
- text.prepend("\n") if config[:raw_text]
- text = text.coloring(/@[0-9A-Za-z_]+/) { |i| color_of(i) }
- text = text.coloring(/(^#[^\s]+)|(\s+#[^\s]+)/) { |i| color_of(i) }
- if config[:expand_url]
- entities = (item["retweeted_status"] && item["truncated"]) ? item["retweeted_status"]["entities"] : item["entities"]
- if entities
- entities.values_at("urls", "media").flatten.compact.each do |entity|
- url, expanded_url = entity.values_at("url", "expanded_url")
- if url && expanded_url
- text = text.sub(url, expanded_url)
- end
- end
- end
- end
- text = text.coloring(URI.regexp(["http", "https"]), :url)
-
- if item["_highlights"]
- item["_highlights"].each do |h|
- color = config[:color][:highlight].nil? ? color_of(h).to_i + 10 : :highlight
- text = text.coloring(/#{h}/i, color)
- end
- end
-
- mark = item["_mark"] || ""
-
- status = [
- "#{mark}" + "[#{id}]".c(:info),
- "#{item["user"]["screen_name"].c(color_of(item["user"]["screen_name"]))}:",
- "#{text}",
- (item["user"]["protected"] ? "[P]".c(:notice) : nil),
- info.join(' - ').c(:info)
- ].compact.join(" ")
- puts status
+ item = Item.new(item)
+ puts item.to_status
end
output :delete do |item|
diff --git a/lib/earthquake/twitter.rb b/lib/earthquake/twitter.rb
index 0c09ddb..9949f39 100644
--- a/lib/earthquake/twitter.rb
+++ b/lib/earthquake/twitter.rb
@@ -49,6 +49,23 @@ module Earthquake
options
)
end
+
+ private
+
+ def get_with_entities(path, headers = {})
+ separator =
+ case URI.parse(path).query
+ when nil
+ "?"
+ when ""
+ ""
+ else
+ "&"
+ end
+ get_without_entities(path + separator + "include_entities=1", headers)
+ end
+
+ alias_method_chain :get, :entities
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment