diff --git a/.map b/.map new file mode 100644 index 0000000..2782e3f --- /dev/null +++ b/.map @@ -0,0 +1,60 @@ +=> #c\x85\xAE2w\xBA&,@\xD3\x96\xCAlO*\xB9\x8DkX", @signing_key=#>, + @store= + #, + @rdonly=true, + @table= + {"blocked"=>#, + "conf"=>{"SEED"=>"\x1FL^9\x90e\xF8g\xF2\x83\xB4\xC4>c\x85\xAE2w\xBA&,@\xD3\x96\xCAlO*\xB9\x8DkX", "HEAD.draft"=>nil}, + "messages.count"=>{"@Y4ZFMFQPWCX0S5KD4C4NMFSRCRCT92FY410M4ACFBK3P24RH9MD0.ed25519"=>4}, + "messages"=> + {"%8STBRYR0WYJJRSD8DRA9RT6RF6QD6AKARCDYV17X8REGACHZ41W0.sha256"=> + #, + @body={"a"=>"\"b\""}, + @depth=0, + @kind="unit_test", + @lipmaa=0, + @prev="NONE", + @signature="8581280WEPNQGJ4DA6K0M7W726YVK1QGW5T7EPGZ61V4HV2GD1RKAB5AN8FXREW0NZKYKFANHW64H3YT0RSMMY30T8TBDJJSR0G9E0G.sig.ed25519">, + "%T88VZKCWN33CVD0TFBRPJ13NJHXF19TFRWP8NFJ1JGE5RB5ETC0G.sha256"=> + #, + @body={"c"=>"\"d\""}, + @depth=1, + @kind="unit_test", + @lipmaa=0, + @prev="%8STBRYR0WYJJRSD8DRA9RT6RF6QD6AKARCDYV17X8REGACHZ41W0.sha256", + @signature="60R873HBC5GHGVFWBC3RZBHXTQW0240GNF20JYBR71V4B1Z57HHXJ6N39Y4QZZPD34PQGZEQVMSAXTC71PATXAMWBVDCF2S9S45KM1G.sig.ed25519">, + "%JD4BETS4YH4ZA7CMP4ZHG0R62T5B0EAFDYHNM5S12M04SAF9AJ4G.sha256"=> + #, + @body={"e"=>"\"f\""}, + @depth=2, + @kind="unit_test", + @lipmaa=1, + @prev="%T88VZKCWN33CVD0TFBRPJ13NJHXF19TFRWP8NFJ1JGE5RB5ETC0G.sha256", + @signature="7DH9ZXMVT6RJEX31BPNSJ3XRA3AMPV97A1CPWW4BV0N99FW2JEPSCVQNJP7SZWA1N7BT560Y9EAK4N7AWFHDEFZV9AJ7PS81CVRF600.sig.ed25519">, + "%WTRSWSVA84DK2QMX5FDSNCVSAKQ4AFNPBW6VE93X4SJ1R60WDYMG.sha256"=> + #, + @body={"g"=>"\"h\""}, + @depth=3, + @kind="unit_test", + @lipmaa=2, + @prev="%JD4BETS4YH4ZA7CMP4ZHG0R62T5B0EAFDYHNM5S12M04SAF9AJ4G.sha256", + @signature="6KZZ2816J8V28QZG5EFM1BZAB2TF1HC87YTCQRSN1Q7395K91C9E7KE7DATT99N7XGQEJ5MRCNDS7354C5KN7763C1XVARKWRDG4T1R.sig.ed25519">}, + "messages.by_depth"=> + {"@Y4ZFMFQPWCX0S5KD4C4NMFSRCRCT92FY410M4ACFBK3P24RH9MD0.ed25519.0"=>"%8STBRYR0WYJJRSD8DRA9RT6RF6QD6AKARCDYV17X8REGACHZ41W0.sha256", + "@Y4ZFMFQPWCX0S5KD4C4NMFSRCRCT92FY410M4ACFBK3P24RH9MD0.ed25519.1"=>"%T88VZKCWN33CVD0TFBRPJ13NJHXF19TFRWP8NFJ1JGE5RB5ETC0G.sha256", + "@Y4ZFMFQPWCX0S5KD4C4NMFSRCRCT92FY410M4ACFBK3P24RH9MD0.ed25519.2"=>"%JD4BETS4YH4ZA7CMP4ZHG0R62T5B0EAFDYHNM5S12M04SAF9AJ4G.sha256", + "@Y4ZFMFQPWCX0S5KD4C4NMFSRCRCT92FY410M4ACFBK3P24RH9MD0.ed25519.3"=>"%WTRSWSVA84DK2QMX5FDSNCVSAKQ4AFNPBW6VE93X4SJ1R60WDYMG.sha256"}, + "peers"=>#}, + @thread_safe=false, + @ultra_safe=true>>> diff --git a/README.md b/README.md index d39de57..dc0e05e 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,7 @@ TODO - [X] Check block list before ingesting bundles. - [X] Need a way of importing / exporting a feeds blobs. (see "Bundle Brainstorming" below) - [X] Need a way of adding peers messages / gossip to bundles. (see "Bundle Brainstorming" below) + - [ ] Rename `who_am_i` as `get_who_am_i` to follow VERB + NOUN convention. - [ ] Update README.md / tutorial.rb (user manual for `Pigeon::Database`). - [ ] Update spec document CLI usage examples to reflect API changes in 2020. - [ ] Publish to RubyGems diff --git a/a.gif b/a.gif new file mode 100644 index 0000000..ed902d4 Binary files /dev/null and b/a.gif differ diff --git a/b.gif b/b.gif new file mode 100644 index 0000000..a4cd0bd Binary files /dev/null and b/b.gif differ diff --git a/bin/pigeon-cli b/bin/pigeon-cli index 95f6c46..3e5974a 100755 --- a/bin/pigeon-cli +++ b/bin/pigeon-cli @@ -41,13 +41,13 @@ module Pigeon raise ConfigAlreadyExists end $db = Pigeon::Database.new - puts db.local_identity.multihash + puts db.who_am_i.multihash end desc "show", "Prints your identiy string to STDOUT" def show - puts db.local_identity.multihash + puts db.who_am_i.multihash end end @@ -56,7 +56,7 @@ module Pigeon def set(data = "") blob = (data != "") ? data : STDIN.read - puts db.put_blob(blob) + puts db.add_blob(blob) end desc "get", "Read arbitrary data from the database" @@ -103,9 +103,9 @@ module Pigeon def append(key, raw_value = "") v = (raw_value != "") ? raw_value : STDIN.read - if db.current_draft + if db.get_draft db.update_draft(key, v) - puts db.current_draft.render_as_draft + puts db.get_draft.render_as_draft else bail("You must create a draft first") end @@ -114,13 +114,13 @@ module Pigeon desc "show", "Print current message to STDOUT." def show - puts db.current_draft.render_as_draft + puts db.get_draft.render_as_draft end desc "sign", "Commit current DRAFT to local feed." def sign - puts db.publish_draft(db.current_draft).render + puts db.publish_draft(db.get_draft).render end end @@ -128,13 +128,13 @@ module Pigeon desc "create", "Create a pigeon bundle file" def create(file_path = Pigeon::DEFAULT_BUNDLE_PATH) - db.create_bundle(file_path) + db.save_bundle(file_path) end desc "ingest", "Ingest a pigeon bundle file" def ingest(file_path = Pigeon::DEFAULT_BUNDLE_PATH) - db.ingest_bundle(file_path) + db.publish_bundle(file_path) end end @@ -148,13 +148,13 @@ module Pigeon desc "find-all", "Find all message IDs of a particular identity." def find_all(author = nil) - puts db.find_all_messages(author).join(Pigeon::CR) + Pigeon::CR + puts db.all_messages(author).join(Pigeon::CR) + Pigeon::CR end desc "last", "Grab your last message. INTERNAL USE ONLY" def last - me = db.local_identity + me = db.who_am_i mcount = db.get_message_count_for(me.multihash) multihash = db.get_message_by_depth(me.multihash, mcount - 1) puts multihash @@ -165,7 +165,7 @@ module Pigeon desc "status", "Show various information about the `.pgn` directory" def status - me = db.local_identity.multihash + me = db.who_am_i.multihash mine = db.get_message_count_for(me) puts " -`. Pigeon Protocol Ruby Client @@ -173,7 +173,7 @@ module Pigeon _) ( Peers: #{db.all_peers.count} / ) Blocked: #{db.all_blocks.count} /_,' / Msgs Published: #{mine} - \\ / Msgs Total: #{db.find_all_messages.count} + \\ / Msgs Total: #{db.all_messages.count} ===m\" \"m=== Your local identity hash: #{me} diff --git a/c.gif b/c.gif new file mode 100644 index 0000000..38b1f66 Binary files /dev/null and b/c.gif differ diff --git a/lib/pigeon.rb b/lib/pigeon.rb index be336d8..d45c457 100644 --- a/lib/pigeon.rb +++ b/lib/pigeon.rb @@ -154,7 +154,7 @@ module Pigeon end def self.publish_draft(db, draft) - author = db.local_identity + author = db.who_am_i mhash = author.multihash template = MessageSerializer.new(draft) depth = db.get_message_count_for(mhash) @@ -173,7 +173,7 @@ module Pigeon end def self.update_draft(db, key, value) - draft = db.current_draft + draft = db.get_draft draft[key] = value db.save_draft(draft) return draft.body[key] diff --git a/lib/pigeon/database.rb b/lib/pigeon/database.rb index df5a338..2b48ed0 100644 --- a/lib/pigeon/database.rb +++ b/lib/pigeon/database.rb @@ -1,6 +1,6 @@ module Pigeon class Database - attr_reader :local_identity + attr_reader :who_am_i def initialize(path: PIGEON_DB_PATH) @store = Pigeon::Storage.new(path: path) @@ -16,10 +16,10 @@ module Pigeon def all_peers(); store.all_peers(); end # === MESSAGES - def find_all_messages(mhash = nil); store.find_all_messages(mhash); end + def all_messages(mhash = nil); store.all_messages(mhash); end def message_saved?(multihash); store.message_saved?(multihash); end - def save_message(msg_obj) + def _save_message(msg_obj) store.insert_message(Helpers.verify_message(self, msg_obj)) end @@ -33,19 +33,19 @@ module Pigeon store.get_message_by_depth(multihash, depth) end - def create_message(kind, params) + def add_message(kind, params) publish_draft(new_draft(kind: kind, body: params)) end # Store a message that someone (not the LocalIdentity) # has authored. - def ingest_message(author:, - body:, - depth:, - kind:, - lipmaa:, - prev:, - signature:) + def _ingest_message(author:, + body:, + depth:, + kind:, + lipmaa:, + prev:, + signature:) msg = Message.new(author: RemoteIdentity.new(author), kind: kind, body: body, @@ -53,11 +53,11 @@ module Pigeon lipmaa: lipmaa, signature: signature, depth: depth) - save_message(msg) + _save_message(msg) end # === DRAFTS - def reset_current_draft; set_config(CURRENT_DRAFT, nil); end + def reset_draft; add_config(CURRENT_DRAFT, nil); end def new_draft(kind:, body: {}) old = get_config(CURRENT_DRAFT) @@ -68,11 +68,11 @@ module Pigeon end def save_draft(draft) - set_config(CURRENT_DRAFT, draft) + add_config(CURRENT_DRAFT, draft) draft end - def current_draft + def get_draft draft = store.get_config(CURRENT_DRAFT) if draft return draft @@ -84,20 +84,20 @@ module Pigeon def update_draft(k, v); Helpers.update_draft(self, k, v); end def reset_draft - set_config(CURRENT_DRAFT, nil) + add_config(CURRENT_DRAFT, nil) end # Author a new message. - def publish_draft(draft = self.current_draft) + def publish_draft(draft = self.get_draft) Helpers.publish_draft(self, draft) end # === BUNDLES - def create_bundle(file_path = DEFAULT_BUNDLE_PATH) + def save_bundle(file_path = DEFAULT_BUNDLE_PATH) # Fetch messages for all peers - peers = all_peers + [local_identity.multihash] + peers = all_peers + [who_am_i.multihash] messages = peers.map do |peer| - find_all_messages(peer) + all_messages(peer) .map { |multihash| read_message(multihash) } .sort_by(&:depth) end.flatten @@ -114,10 +114,11 @@ module Pigeon content = messages .map { |message| message.render } .join(BUNDLE_MESSAGE_SEPARATOR) + File.join(file_path, "gossip.pgn") File.write(File.join(file_path, "gossip.pgn"), content + CR) end - def ingest_bundle(file_path = DEFAULT_BUNDLE_PATH) + def publish_bundle(file_path = DEFAULT_BUNDLE_PATH) bundle = File.read(File.join(file_path, "gossip.pgn")) tokens = Pigeon::Lexer.tokenize(bundle) Pigeon::Parser.parse(self, tokens) @@ -125,11 +126,11 @@ module Pigeon # === BLOBS def get_blob(b); store.get_blob(b); end - def put_blob(b); store.put_blob(b); end + def add_blob(b); store.add_blob(b); end # === DB Management def get_config(k); store.get_config(k); end - def set_config(k, v); store.set_config(k, v); end + def add_config(k, v); store.add_config(k, v); end def reset_database; store.reset; init_ident; end private @@ -139,11 +140,11 @@ module Pigeon def init_ident secret = get_config(SEED_CONFIG_KEY) if secret - @local_identity = LocalIdentity.new(secret) + @who_am_i = LocalIdentity.new(secret) else new_seed = SecureRandom.random_bytes(Ed25519::KEY_SIZE) - set_config(SEED_CONFIG_KEY, new_seed) - @local_identity = LocalIdentity.new(new_seed) + add_config(SEED_CONFIG_KEY, new_seed) + @who_am_i = LocalIdentity.new(new_seed) end end end diff --git a/lib/pigeon/parser.rb b/lib/pigeon/parser.rb index 0156069..40ea00c 100644 --- a/lib/pigeon/parser.rb +++ b/lib/pigeon/parser.rb @@ -41,7 +41,7 @@ module Pigeon def finish_this_message! @scratchpad.freeze unless @db.peer_blocked?(@scratchpad.fetch(:author)) - @results.push(@db.ingest_message(**@scratchpad)) + @results.push(@db._ingest_message(**@scratchpad)) end reset_scratchpad end diff --git a/lib/pigeon/storage.rb b/lib/pigeon/storage.rb index 711abc9..7234683 100644 --- a/lib/pigeon/storage.rb +++ b/lib/pigeon/storage.rb @@ -43,7 +43,7 @@ module Pigeon read { store[CONF_NS][key] } end - def set_config(key, value) + def add_config(key, value) write do a = store.fetch(CONF_NS) raise "FIX SAVED DRAFTS" if value.instance_variable_get(:@db) @@ -51,7 +51,7 @@ module Pigeon end end - def put_blob(data) + def add_blob(data) size = data.bytesize if (size > BLOB_BYTE_LIMIT) raise "Blob size limit is #{BLOB_BYTE_LIMIT} bytes. Got #{size}" @@ -79,7 +79,7 @@ module Pigeon read { store[COUNT_INDEX_NS][mhash] || 0 } end - def find_all_messages(author) + def all_messages(author) if author all = [] depth = -1 diff --git a/pigeon.db b/pigeon.db index 6e8b1a9..4636c73 100644 Binary files a/pigeon.db and b/pigeon.db differ diff --git a/spec/pigeon/bundle_spec.rb b/spec/pigeon/bundle_spec.rb index 1c8921d..6197c6a 100644 --- a/spec/pigeon/bundle_spec.rb +++ b/spec/pigeon/bundle_spec.rb @@ -13,35 +13,41 @@ RSpec.describe Pigeon::Message do end def create_fake_messages - blobs = [db.create_message(db.put_blob("one"), { "a" => "b" }), - db.create_message("a", { db.put_blob("two") => "b" }), - db.create_message("a", { "b" => db.put_blob("three") })] + blobs = [db.add_message(db.add_blob("one"), { "a" => "b" }), + db.add_message("a", { db.add_blob("two") => "b" }), + db.add_message("a", { "b" => db.add_blob("three") })] normal = (1..10) .to_a .map do |n| { "foo" => ["bar", "123", SecureRandom.uuid].sample } end - .map do |d| db.create_message(SecureRandom.uuid, d) end + .map do |d| db.add_message(SecureRandom.uuid, d) end blobs + normal end it "creates a bundle" do expected_bundle = create_fake_messages.map(&:render).join("\n\n") + "\n" - db.create_bundle + db.save_bundle actual_bundle = File.read(File.join(Pigeon::DEFAULT_BUNDLE_PATH, "gossip.pgn")) expect(expected_bundle).to eq(actual_bundle) end it "does not crash when ingesting old messages" do create_fake_messages - db.create_bundle - db.ingest_bundle + db.save_bundle + db.publish_bundle end it "does not ingest messages from blocked peers" do db.reset_database antagonist = "@PPJQ3Q36W258VQ1NKYY2G7VW24J8NMAACHXCD83GCQ3K8F4C9X2G.ed25519" db.block_peer(antagonist) - db.ingest_bundle("./spec/fixtures/x") - expect(db.find_all_messages.count).to eq(0) + db.publish_bundle("./spec/fixtures/x") + expect(db.all_messages.count).to eq(0) + end + + it "ingests a bundle's blobs" do + db.reset_database + db.publish_bundle("./spec/fixtures/has_blobs") + expect(db.all_messages.count).to eq(0) end end diff --git a/spec/pigeon/draft_spec.rb b/spec/pigeon/draft_spec.rb index c0b624a..f900b59 100644 --- a/spec/pigeon/draft_spec.rb +++ b/spec/pigeon/draft_spec.rb @@ -12,8 +12,8 @@ RSpec.describe Pigeon::Draft do db.new_draft(kind: "unit_test") logo = File.read("./logo.png") db.update_draft("a", "bar") - db.update_draft("b", db.put_blob(logo)) - db.current_draft + db.update_draft("b", db.add_blob(logo)) + db.get_draft end MSG = [ @@ -28,7 +28,7 @@ RSpec.describe Pigeon::Draft do ].join("\n") it "renders a message" do - pk = db.local_identity.multihash + pk = db.who_am_i.multihash actual = message.render_as_draft expected = MSG.gsub("___", pk) expect(actual).to start_with(expected) @@ -37,7 +37,7 @@ RSpec.describe Pigeon::Draft do it "creates a new message" do db.reset_draft db.new_draft(kind: "unit_test") - hash = db.put_blob(File.read("./logo.png")) + hash = db.add_blob(File.read("./logo.png")) expectations = { kind: "unit_test", body: { @@ -52,7 +52,7 @@ RSpec.describe Pigeon::Draft do expect(message.kind).to eq("unit_test") expect(message.body).to eq(expectations.fetch(:body)) expectations.map do |k, v| - left = db.current_draft.send(k) + left = db.get_draft.send(k) expect(left).to eq(v) end end diff --git a/spec/pigeon/message_spec.rb b/spec/pigeon/message_spec.rb index e2936f1..9e57f6b 100644 --- a/spec/pigeon/message_spec.rb +++ b/spec/pigeon/message_spec.rb @@ -4,10 +4,10 @@ RSpec.describe Pigeon::Message do def reset_draft(params) db.reset_draft db.new_draft(kind: "unit_test", body: params) - db.current_draft + db.get_draft end - def create_message(params) + def add_message(params) draft = reset_draft(params) db.publish_draft(draft) end @@ -19,11 +19,11 @@ RSpec.describe Pigeon::Message do end let(:draft) do - hash = db.put_blob(File.read("./logo.png")) + hash = db.add_blob(File.read("./logo.png")) reset_draft({ "a" => "bar", "b" => hash }) end - let(:templated_message) { create_message({ "a" => "b" }) } + let(:templated_message) { add_message({ "a" => "b" }) } let (:template) do Pigeon::MessageSerializer.new(templated_message) @@ -31,12 +31,12 @@ RSpec.describe Pigeon::Message do it "discards a draft after signing" do db.publish_draft(draft) - expect { db.current_draft }.to raise_error("THERE IS NO DRAFT. CREATE ONE FIRST.") + expect { db.get_draft }.to raise_error("THERE IS NO DRAFT. CREATE ONE FIRST.") end it "creates a single message" do message = db.publish_draft(draft) - expect(message.author.multihash).to eq(db.local_identity.multihash) + expect(message.author.multihash).to eq(db.who_am_i.multihash) expect(message.body).to eq(draft.body) expect(message.depth).to eq(0) expect(message.kind).to eq("unit_test") @@ -79,10 +79,10 @@ RSpec.describe Pigeon::Message do end it "verifies accuracy of hash chain" do - m1 = create_message({ "a" => "b" }) - m2 = create_message({ "c" => "d" }) - m3 = create_message({ "e" => "f" }) - m4 = create_message({ "g" => "h" }) + m1 = add_message({ "a" => "b" }) + m2 = add_message({ "c" => "d" }) + m3 = add_message({ "e" => "f" }) + m4 = add_message({ "g" => "h" }) expect(m1.prev).to eq(Pigeon::NOTHING) expect(m2.prev).to be @@ -100,7 +100,7 @@ RSpec.describe Pigeon::Message do body[SecureRandom.hex(6)] = SecureRandom.hex(6) end expect do - create_message(body) + add_message(body) end.to raise_error(Pigeon::Helpers::MessageSizeError, error) end @@ -112,7 +112,7 @@ RSpec.describe Pigeon::Message do plaintext = template.render_without_signature # Make fake pairs of data for cross-checking - key1 = db.local_identity.instance_variable_get(:@signing_key) + key1 = db.who_am_i.instance_variable_get(:@signing_key) key2 = Ed25519::SigningKey.new(secret) sig1 = key1.sign(plaintext) diff --git a/spec/pigeon/parser_spec.rb b/spec/pigeon/parser_spec.rb index d5f45bc..5d19512 100644 --- a/spec/pigeon/parser_spec.rb +++ b/spec/pigeon/parser_spec.rb @@ -30,7 +30,7 @@ RSpec.describe Pigeon::Lexer do end it "ingests and reconstructs a bundle" do - messages = db.ingest_bundle("./spec/fixtures/normal") + messages = db.publish_bundle("./spec/fixtures/normal") expect(messages.length).to eq(10) expect(messages.map(&:class).uniq).to eq([Pigeon::Message]) re_bundled = messages.map(&:render).join("\n\n") + "\n" diff --git a/spec/pigeon/storage_spec.rb b/spec/pigeon/storage_spec.rb index 0525a96..0058945 100644 --- a/spec/pigeon/storage_spec.rb +++ b/spec/pigeon/storage_spec.rb @@ -12,22 +12,22 @@ RSpec.describe Pigeon::Storage do end it "sets a config" do - db.set_config("FOO", "BAR") + db.add_config("FOO", "BAR") value = db.get_config("FOO") expect(value).to eq("BAR") - db.set_config("FOO", nil) + db.add_config("FOO", nil) value = db.get_config("FOO") expect(value).to eq(nil) end it "manages configs" do - db.set_config("FOO", "BAR") + db.add_config("FOO", "BAR") value = db.get_config("FOO") expect(value).to eq("BAR") end it "manages blobs" do - logo_hash = db.put_blob(LOGO_BLOB) + logo_hash = db.add_blob(LOGO_BLOB) expect(db.get_blob(logo_hash)).to eq(LOGO_BLOB) end @@ -48,27 +48,27 @@ RSpec.describe Pigeon::Storage do end it "finds all authored by a particular feed" do - ingested_messages = db.ingest_bundle("./spec/fixtures/normal") + ingested_messages = db.publish_bundle("./spec/fixtures/normal") author = ingested_messages.first.author.multihash - actual_messages = db.find_all_messages(author) - search_results = db.find_all_messages(author) + actual_messages = db.all_messages(author) + search_results = db.all_messages(author) end it "finds all messages" do msgs = [ - db.create_message("strings", { + db.add_message("strings", { "example_1.1" => "This is a string.", "example=_." => "A second string.", }), - db.create_message("d", { - "e" => db.put_blob(File.read("./logo.png")), + db.add_message("d", { + "e" => db.add_blob(File.read("./logo.png")), }), - db.create_message("g", { - "me_myself_and_i" => db.local_identity.multihash, + db.add_message("g", { + "me_myself_and_i" => db.who_am_i.multihash, }), ] - me = db.local_identity.multihash - results = db.find_all_messages(me) + me = db.who_am_i.multihash + results = db.all_messages(me) expect(results.length).to eq(3) expect(msgs[0].multihash).to eq(results[0]) expect(msgs[1].multihash).to eq(results[1]) diff --git a/tutorial.rb b/tutorial.rb index 52ffb22..00f0319 100644 --- a/tutorial.rb +++ b/tutorial.rb @@ -1,31 +1,36 @@ -require "pigeon" +# add_blob +# add_config +# add_message +# add_peer +# all_blocks +# all_messages +# all_peers +# block_peer +# get_blob +# get_config +# get_draft +# get_message_by_depth +# get_message_count_for +# message_saved? +# peer_blocked? +# who_am_i +# new_draft +# publish_bundle +# publish_draft +# read_message +# remove_peer +# reset_database +# reset_draft +# save_bundle +# save_draft +# update_draft + +require_relative "lib/pigeon" require "pry" - -db = Pigeon::Database.new(path: "my.db") - -db.reset_draft -db.current_draft -db.reset_draft -db.publish_draft -db.save_draft -db.save_message -db.reset_current_draft -db.message_saved? -db.read_message -db.create_message -db.find_all_messages -db.get_message_by_depth -db.get_message_count_for -db.local_identity -db.remove_peer -db.add_peer -db.block_peer -db.all_peers -db.all_blocks -db.get_blob -db.put_blob -db.create_bundle -db.get_config -db.ingest_bundle -db.set_config -db.reset_database +files = %w(a.gif b.gif c.gif) +body = { "what" => "A simple bundle with a few blobs" } +db = Pigeon::Database.new(path: "new.db") +db.add_message("description", body) +files.map { |file| db.add_blob(file) } +binding.pry +db.save_bundle("./spec/fixtures/has_blobs")