mirror of https://github.com/Calamitous/iris.git
Add reply-ro-topic functionality
This commit is contained in:
parent
12cb082e4e
commit
20028de37e
125
iris.rb
125
iris.rb
|
@ -104,6 +104,12 @@ class Corpus
|
||||||
@@corpus = Config.find_files.map { |filepath| IrisFile.load_messages(filepath) }.flatten.sort_by(&:timestamp)
|
@@corpus = Config.find_files.map { |filepath| IrisFile.load_messages(filepath) }.flatten.sort_by(&:timestamp)
|
||||||
@@topics = @@corpus.select{ |m| m.parent == nil }
|
@@topics = @@corpus.select{ |m| m.parent == nil }
|
||||||
@@my_corpus = IrisFile.load_messages.sort_by(&:timestamp)
|
@@my_corpus = IrisFile.load_messages.sort_by(&:timestamp)
|
||||||
|
@@all_hash_to_index = @@corpus.reduce({}) { |agg, msg| agg[msg.hash] = @@corpus.index(msg); agg }
|
||||||
|
@@all_parent_hash_to_index = @@corpus.reduce({}) do |agg, msg|
|
||||||
|
agg[msg.parent] ||= []
|
||||||
|
agg[msg.parent] << @@corpus.index(msg)
|
||||||
|
agg
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.all
|
def self.all
|
||||||
|
@ -117,18 +123,46 @@ class Corpus
|
||||||
def self.mine
|
def self.mine
|
||||||
@@my_corpus
|
@@my_corpus
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.find_message_by_hash(hash)
|
||||||
|
return nil unless hash
|
||||||
|
index = @@all_hash_to_index[hash]
|
||||||
|
return nil unless index
|
||||||
|
all[index]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.find_all_by_parent_hash(hash)
|
||||||
|
return [] unless hash
|
||||||
|
indexes = @@all_parent_hash_to_index[hash]
|
||||||
|
return [] unless indexes
|
||||||
|
indexes.map{ |idx| all[idx] }
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.find_topic(topic_id)
|
||||||
|
if topic_id.to_i == 0
|
||||||
|
# This must be a hash, handle appropriately
|
||||||
|
msg = find_message_by_hash(topic_id)
|
||||||
|
puts 'WARNING: Expected a topic but got a reply!' unless msg.is_topic?
|
||||||
|
msg
|
||||||
|
else
|
||||||
|
# This must be an index, handle appropriately
|
||||||
|
index = topic_id.to_i - 1
|
||||||
|
return topics[index] if index >= 0 && index < topics.length
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class Message
|
class Message
|
||||||
FILE_FORMAT = 'v2'
|
FILE_FORMAT = 'v2'
|
||||||
|
|
||||||
attr_reader :timestamp, :hash, :edit_hash, :author, :parent, :message, :errors
|
attr_reader :timestamp, :edit_hash, :author, :parent, :message, :errors
|
||||||
|
|
||||||
def initialize(message, author = Config::AUTHOR, parent = nil, timestamp = Time.now.utc.iso8601, edit_hash = nil)
|
def initialize(message, parent = nil, author = Config::AUTHOR, timestamp = Time.now.utc.iso8601, edit_hash = nil)
|
||||||
@parent = parent
|
@parent = parent
|
||||||
@author = author
|
@author = author
|
||||||
@timestamp = timestamp
|
@timestamp = timestamp
|
||||||
@message = message
|
@message = message
|
||||||
|
@hash = hash
|
||||||
@errors = []
|
@errors = []
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -136,7 +170,7 @@ class Message
|
||||||
data = payload if payload.is_a?(Hash)
|
data = payload if payload.is_a?(Hash)
|
||||||
data = JSON.parse(payload) if payload.is_a?(String)
|
data = JSON.parse(payload) if payload.is_a?(String)
|
||||||
|
|
||||||
loaded_message = self.new(data['data']['message'], data['data']['author'], data['data']['parent'], data['data']['timestamp'], data['edit_hash'])
|
loaded_message = self.new(data['data']['message'], data['data']['parent'], data['data']['author'], data['data']['timestamp'], data['edit_hash'])
|
||||||
loaded_message.validate_hash(data['hash'])
|
loaded_message.validate_hash(data['hash'])
|
||||||
loaded_message
|
loaded_message
|
||||||
end
|
end
|
||||||
|
@ -151,7 +185,7 @@ class Message
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_hash(test_hash)
|
def validate_hash(test_hash)
|
||||||
if hash != test_hash
|
if self.hash != test_hash
|
||||||
@errors << "Broken hash: expected '#{hash}', got '#{test_hash}'"
|
@errors << "Broken hash: expected '#{hash}', got '#{test_hash}'"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -167,7 +201,10 @@ class Message
|
||||||
end
|
end
|
||||||
|
|
||||||
def hash(payload = nil)
|
def hash(payload = nil)
|
||||||
payload ||= unconfirmed_payload.to_json
|
if payload.nil?
|
||||||
|
return @hash if @hash
|
||||||
|
payload = unconfirmed_payload.to_json
|
||||||
|
end
|
||||||
Base64.encode64(Digest::SHA1.digest(payload))
|
Base64.encode64(Digest::SHA1.digest(payload))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -183,15 +220,31 @@ class Message
|
||||||
[head, message_stub].join(' | ')
|
[head, message_stub].join(' | ')
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_topic_display
|
def leader_text
|
||||||
|
is_topic? ? '***' : '==='
|
||||||
|
end
|
||||||
|
|
||||||
|
def verb_text
|
||||||
|
is_topic? ? 'posted' : 'replied'
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_display
|
||||||
[
|
[
|
||||||
"On #{timestamp}, #{author} posted...",
|
"#{leader_text} On #{timestamp}, #{author} #{verb_text}...",
|
||||||
'-' * Display::WIDTH,
|
'-' * Display::WIDTH,
|
||||||
message,
|
message,
|
||||||
'-' * Display::WIDTH
|
'-' * Display::WIDTH
|
||||||
].join("\n")
|
].join("\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_topic_display
|
||||||
|
[to_display] + replies.map(&:to_display)
|
||||||
|
end
|
||||||
|
|
||||||
|
def replies
|
||||||
|
Corpus.find_all_by_parent_hash(hash)
|
||||||
|
end
|
||||||
|
|
||||||
def is_topic?
|
def is_topic?
|
||||||
parent.nil?
|
parent.nil?
|
||||||
end
|
end
|
||||||
|
@ -227,7 +280,7 @@ class Display
|
||||||
end
|
end
|
||||||
|
|
||||||
class Interface
|
class Interface
|
||||||
ONE_SHOTS = %w{help topics create quit freshen}
|
ONE_SHOTS = %w{help topics create quit freshen reply}
|
||||||
CMD_MAP = {
|
CMD_MAP = {
|
||||||
't' => 'topics',
|
't' => 'topics',
|
||||||
'topics' => 'topics',
|
'topics' => 'topics',
|
||||||
|
@ -245,10 +298,55 @@ class Interface
|
||||||
}
|
}
|
||||||
|
|
||||||
def browsing_handler(line)
|
def browsing_handler(line)
|
||||||
cmd = line.split(/\s/).first
|
tokens = line.split(/\s/)
|
||||||
|
cmd = tokens.first
|
||||||
cmd = CMD_MAP[cmd] || cmd
|
cmd = CMD_MAP[cmd] || cmd
|
||||||
return self.send(cmd.to_sym) if ONE_SHOTS.include?(cmd)
|
return self.send(cmd.to_sym) if ONE_SHOTS.include?(cmd) && tokens.length == 1
|
||||||
return show_topic(cmd) if cmd =~ /^\d+$/
|
return show_topic(cmd) if cmd =~ /^\d+$/
|
||||||
|
# We must have args, let's handle 'em
|
||||||
|
arg = tokens.last
|
||||||
|
return reply(arg) if cmd == 'reply'
|
||||||
|
puts 'Unrecognized command. Type "help" for a list of available commands.'
|
||||||
|
end
|
||||||
|
|
||||||
|
def reply(topic_id = nil)
|
||||||
|
topic_id ||= @reply_topic
|
||||||
|
unless topic_id
|
||||||
|
puts "I can't reply to nothing! Include a topic ID or view a topic to reply to."
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if parent = Corpus.find_topic(topic_id)
|
||||||
|
@reply_topic = parent.hash
|
||||||
|
else
|
||||||
|
puts "Could not reply; unable to find a topic with ID '#{topic_id}'"
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
@mode = :replying
|
||||||
|
@text_buffer = ''
|
||||||
|
title = Corpus.find_topic(parent.hash).truncated_message(80)
|
||||||
|
puts "Writing a reply to topic '#{title}'. Type a period on a line by itself to end message."
|
||||||
|
end
|
||||||
|
|
||||||
|
def replying_handler(line)
|
||||||
|
if line !~ /^\.$/
|
||||||
|
if @text_buffer.empty?
|
||||||
|
@text_buffer = line
|
||||||
|
else
|
||||||
|
@text_buffer = [@text_buffer, line].join("\n")
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if @text_buffer.length <= 1
|
||||||
|
puts 'Empty message, discarding...'
|
||||||
|
else
|
||||||
|
Message.new(@text_buffer, @reply_topic).save!
|
||||||
|
puts 'Reply saved!'
|
||||||
|
end
|
||||||
|
@reply_topic = nil
|
||||||
|
@mode = :browsing
|
||||||
end
|
end
|
||||||
|
|
||||||
def creating_handler(line)
|
def creating_handler(line)
|
||||||
|
@ -273,12 +371,15 @@ class Interface
|
||||||
def handle(line)
|
def handle(line)
|
||||||
return browsing_handler(line) if @mode == :browsing
|
return browsing_handler(line) if @mode == :browsing
|
||||||
return creating_handler(line) if @mode == :creating
|
return creating_handler(line) if @mode == :creating
|
||||||
|
return replying_handler(line) if @mode == :replying
|
||||||
end
|
end
|
||||||
|
|
||||||
def show_topic(num)
|
def show_topic(num)
|
||||||
index = num.to_i - 1
|
index = num.to_i - 1
|
||||||
if index >= 0 && index < Corpus.topics.length
|
if index >= 0 && index < Corpus.topics.length
|
||||||
puts Corpus.topics[index].to_topic_display
|
msg = Corpus.topics[index]
|
||||||
|
@reply_topic = msg.hash
|
||||||
|
puts msg.to_topic_display
|
||||||
else
|
else
|
||||||
puts 'Could not find a topic with that ID'
|
puts 'Could not find a topic with that ID'
|
||||||
end
|
end
|
||||||
|
@ -312,7 +413,7 @@ class Interface
|
||||||
def create
|
def create
|
||||||
@mode = :creating
|
@mode = :creating
|
||||||
@text_buffer = ''
|
@text_buffer = ''
|
||||||
puts 'Writing a new topic. Type a period on a line by itself to end.'
|
puts 'Writing a new topic. Type a period on a line by itself to end message.'
|
||||||
end
|
end
|
||||||
|
|
||||||
def topics
|
def topics
|
||||||
|
|
Loading…
Reference in New Issue