mirror of https://github.com/Calamitous/iris.git
Compare commits
6 Commits
d907c7a3b3
...
972f1a8854
Author | SHA1 | Date |
---|---|---|
Eric B. Budd | 972f1a8854 | |
Eric B. Budd | a2a9c6078d | |
Eric B. Budd | ed124e7389 | |
Eric B. Budd | 5b925dc0ae | |
Eric B. Budd | 8c858464e0 | |
Eric B. Budd | fea37fa4dc |
|
@ -1,5 +1,12 @@
|
|||
# Changelog
|
||||
|
||||
## 1.1.1
|
||||
* Make discarded message response more prominent
|
||||
* Try nano if /usr/bin/vim is not set
|
||||
* Expand the technical documentation
|
||||
* Flesh out some tests
|
||||
* Clean up TODO file
|
||||
|
||||
## 1.1.0
|
||||
* Iris now composes messages with $EDITOR instead of using an internal editor
|
||||
* Remove (broken) feature that automatically selects a reply when not provided with a topic ID
|
||||
|
|
74
README.md
74
README.md
|
@ -36,7 +36,7 @@ Iris has a readline interface that can be used to navigate the message corpus.
|
|||
|
||||
```bash
|
||||
%> iris
|
||||
Welcome to Iris v. 1.1.0. Type "help" for a list of commands.; Ctrl-D or 'quit' to leave.
|
||||
Welcome to Iris v. 1.1.1. Type "help" for a list of commands.; Ctrl-D or 'quit' to leave.
|
||||
|
||||
| ID | U | TIMESTAMP | AUTHOR | TITLE
|
||||
| 1 | | 2018-01-24T05:49:53Z | jimmy_foo@ctrl-c.club | Welcome!
|
||||
|
@ -368,7 +368,7 @@ This outputs the current version of Iris, along with messsage, topic, and author
|
|||
```bash
|
||||
jennie_minnie@ctrl-c.club~> info
|
||||
|
||||
Iris 1.1.0
|
||||
Iris 1.1.1
|
||||
22 topics, 0 unread.
|
||||
50 messages, 0 unread.
|
||||
10 authors.
|
||||
|
@ -402,7 +402,7 @@ iris --version
|
|||
```
|
||||
|
||||
```bash
|
||||
Iris 1.1.0
|
||||
Iris 1.1.1
|
||||
```
|
||||
|
||||
---
|
||||
|
@ -418,7 +418,7 @@ iris --stats
|
|||
```
|
||||
|
||||
```bash
|
||||
Iris 1.1.0
|
||||
Iris 1.1.1
|
||||
22 topics, 0 unread.
|
||||
50 messages, 0 unread.
|
||||
10 authors.
|
||||
|
@ -657,7 +657,7 @@ In order to operate correctly and safely, this file _must_ be:
|
|||
* World-readable
|
||||
* Owner-writable
|
||||
* Non-executable
|
||||
* Owned by the user account that will be storing messages for
|
||||
* Owned by the user account that it will be storing messages for
|
||||
|
||||
```bash
|
||||
%> ls -la ~/.iris.messages
|
||||
|
@ -665,7 +665,71 @@ In order to operate correctly and safely, this file _must_ be:
|
|||
```
|
||||
|
||||
### Messages
|
||||
|
||||
Messages fall into one of two categories: topics and replies. Topics are top-level messages. Replies are messages that are attached to a topic.
|
||||
|
||||
The message structure is as follows:
|
||||
|
||||
```
|
||||
{
|
||||
"hash": str,
|
||||
"edit_hash": str,
|
||||
"is_deleted": bool,
|
||||
"data": {
|
||||
"author": str,
|
||||
"parent": str,
|
||||
"timestamp": str,
|
||||
"message": str
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Each field is as follows:
|
||||
|
||||
* author: The username of the user who created the message, with the server hostname attached with an @ symbol (ie. `jerry_berry@ctrl-c.club`).
|
||||
* message: The text of the message. The first line is the title of the message.
|
||||
* hash: Each message is SHA1 hashed for verification and uniqueness. The author, parent hash, timestamp, and message values go into the hash. (see [Message Hash](#message-hash) for details)
|
||||
* parent: If the message is a reply, this holds the hash of the topic it's associated with.
|
||||
* timestamp: The GMT timestamp of when the message was created.
|
||||
* edit_hash: When a message is edited, a new message is created-- this field holds the hash of the modified message. The client follows the chain of edit hashes to end up at the final, edited message to display. This lets us keep an "undo" history (not yet implemented) and is a marker so the client can display a marker that the message has been edited.
|
||||
* is_deleted: This is a boolean field that marks whether a message has been deleted. The message is retained so that the structure of topics and replies can be maintained.
|
||||
* errors (not saved to the file): This is where any issues are held for display. Examples of errors are unparseable usernames or invalid hashes.
|
||||
|
||||
#### Message Hash
|
||||
|
||||
Each message is SHA1 hashed for verification and uniqueness.
|
||||
|
||||
The hash is created by putting `author`, `parent`, `timestamp`, and `message` go into a JSON-formatted string. This string should include no extra whitespace.
|
||||
|
||||
For example:
|
||||
|
||||
The following message:
|
||||
|
||||
author: `jerry_berry@ctrl-c.club`
|
||||
parent: null
|
||||
timestamp: `2021-11-25T06:35:34Z`
|
||||
message: `Howdy!`
|
||||
|
||||
Would be turned into the following JSON string, in this order:
|
||||
|
||||
```
|
||||
{"author":"jerry_berry@ctrl-c.club","parent":null,"timestamp":"2021-11-25T06:35:34Z","message":"Howdy!"}
|
||||
```
|
||||
|
||||
This string would then be hashed using SHA1:
|
||||
|
||||
```
|
||||
\xBD\xFD[D\xA0\xF0\xBFw`\x14\xF8)\xCA\xC9n\xFA-\x82\xB9\xBC
|
||||
```
|
||||
|
||||
This hash is then base64 encoded:
|
||||
|
||||
```
|
||||
vf1bRKDwv3dgFPgpyslu+i2Cubw=\n
|
||||
```
|
||||
|
||||
This is the "key" that is used to uniquely identify this version of the message.
|
||||
|
||||
##### Bad Hashes
|
||||
#### Edit Chain
|
||||
#### Deleted Messages
|
||||
|
|
4
TODO.md
4
TODO.md
|
@ -10,16 +10,12 @@
|
|||
* Flesh out technical sections
|
||||
|
||||
### Bugs
|
||||
* Replying implicitly to 24 replied to 6 instead-- remove implicit reply?
|
||||
* Is `Time.now.utc.iso8601` working as expected?
|
||||
* Fix bug when people are posting from different time zones
|
||||
* Fix message ordering when editing/deleting multiple messages
|
||||
* Gracefully handle attempt to "r 1 message"
|
||||
|
||||
### Features
|
||||
* Add "unread" marker to topic replies
|
||||
* Allow shelling out to editor for message editing
|
||||
* https://github.com/Calamitous/iris/issues/2
|
||||
* Add pagination/less for long message lists
|
||||
* https://github.com/Calamitous/iris/issues/1
|
||||
* Add local timezone rendering
|
||||
|
|
24
iris.rb
24
iris.rb
|
@ -8,8 +8,21 @@ require 'tempfile'
|
|||
require 'time'
|
||||
# require 'pry' # Only needed for debugging
|
||||
|
||||
class NilClass
|
||||
def presence
|
||||
self
|
||||
end
|
||||
end
|
||||
|
||||
class String
|
||||
def presence
|
||||
return nil if self.length == 0
|
||||
self
|
||||
end
|
||||
end
|
||||
|
||||
class Config
|
||||
VERSION = '1.1.0'
|
||||
VERSION = '1.1.1'
|
||||
MESSAGE_FILE = "#{ENV['HOME']}/.iris.messages"
|
||||
HISTORY_FILE = "#{ENV['HOME']}/.iris.history"
|
||||
IRIS_SCRIPT = __FILE__
|
||||
|
@ -17,6 +30,7 @@ class Config
|
|||
USER = ENV['USER'] || ENV['LOGNAME'] || ENV['USERNAME']
|
||||
HOSTNAME = `hostname -d`.chomp
|
||||
AUTHOR = "#{USER}@#{HOSTNAME}"
|
||||
ENV_EDITOR = ENV['EDITOR'].presence || `which nano`.chomp.presence
|
||||
|
||||
@@debug_mode = false
|
||||
|
||||
|
@ -681,7 +695,7 @@ class Interface
|
|||
message_text = external_editor()
|
||||
|
||||
if message_text.length <= 1
|
||||
Display.say 'Empty message, discarding...'
|
||||
Display.say '{riv Empty message, discarding...}'
|
||||
else
|
||||
Message.new(message_text).save!
|
||||
Display.say 'Topic saved!'
|
||||
|
@ -724,7 +738,7 @@ class Interface
|
|||
message_text = external_editor()
|
||||
|
||||
if message_text.length <= 1
|
||||
Display.say 'Empty message, discarding...'
|
||||
Display.say '{riv Empty message, discarding...}'
|
||||
else
|
||||
Message.new(message_text, reply_topic).save!
|
||||
Display.say 'Reply saved!'
|
||||
|
@ -827,9 +841,9 @@ class Interface
|
|||
tf.flush
|
||||
end
|
||||
|
||||
raise "No `$EDITOR` environment variable set!" unless ENV['EDITOR'] && ENV['EDITOR'].length > 0
|
||||
raise "No `$EDITOR` environment variable set!" unless Config::ENV_EDITOR
|
||||
|
||||
system("#{ENV['EDITOR']} #{tf.path}")
|
||||
system("#{Config::ENV_EDITOR} #{tf.path}")
|
||||
tf.rewind
|
||||
message_text = tf.read
|
||||
tf.unlink
|
||||
|
|
|
@ -4,6 +4,8 @@ require 'mocha/minitest'
|
|||
# This allows the test to pretend that user "jerryberry" is logged in.
|
||||
ENV['USER'] = 'jerryberry'
|
||||
|
||||
ENV['EDITOR'] = 'foo/bar'
|
||||
|
||||
# Set this before loading the code so that the Config constants load correctly.
|
||||
$test_corpus_file = "./tests/iris.messages.json"
|
||||
|
||||
|
@ -34,6 +36,10 @@ describe Config do
|
|||
_(Config::AUTHOR).must_equal "#{Config::USER}@#{Config::HOSTNAME}"
|
||||
end
|
||||
|
||||
it 'has the $EDITOR environment variable' do
|
||||
_(Config::ENV_EDITOR).must_equal 'foo/bar'
|
||||
end
|
||||
|
||||
describe '.find_files' do
|
||||
it 'looks up all the Iris message files on the system' do
|
||||
# I am so sorry about this `expects` clause
|
||||
|
@ -97,10 +103,13 @@ describe Corpus do
|
|||
end
|
||||
|
||||
it 'returns an empty array if the hash is not a parent of any other messages' do
|
||||
_(Corpus.find_all_by_parent_hash(nil)).must_equal []
|
||||
end
|
||||
|
||||
it 'returns an empty array if the hash is not found in the corpus' do
|
||||
_(Corpus.find_all_by_parent_hash('GoofMcDoof')).must_equal []
|
||||
end
|
||||
|
||||
it 'returns an empty array if the hash is not found in the corpus'
|
||||
it 'returns the messages associated with the parent hash'
|
||||
end
|
||||
|
||||
|
@ -110,8 +119,13 @@ describe Corpus do
|
|||
end
|
||||
|
||||
describe 'when an index string is passed in' do
|
||||
it 'returns nil if the topic is not found'
|
||||
it 'returns the associated topic'
|
||||
it 'returns nil if the topic is not found' do
|
||||
assert_nil Corpus.find_topic_by_id('InvalidTopicId')
|
||||
end
|
||||
|
||||
it 'returns the associated topic' do
|
||||
_(Corpus.find_topic_by_id(1).message).must_equal 'Test'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -121,8 +135,13 @@ describe Corpus do
|
|||
end
|
||||
|
||||
describe 'when a hash string is passed in' do
|
||||
it 'returns nil if the topic is not found'
|
||||
it 'returns the associated topic'
|
||||
it 'returns nil if the topic is not found' do
|
||||
assert_nil Corpus.find_topic_by_hash('BadHash')
|
||||
end
|
||||
|
||||
it 'returns the associated topic' do
|
||||
_(Corpus.find_topic_by_hash("gpY2WW/jGcH+BODgySCwDANJlIM=\n").message).must_equal 'Test'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue