Skip to content

Commit

Permalink
add types: TextNoteRepostEvent (kind 6) and GenericRepostEvent (kind 16)
Browse files Browse the repository at this point in the history
  • Loading branch information
bryanmontz committed Aug 9, 2023
1 parent f61b157 commit f637ffc
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 2 deletions.
11 changes: 10 additions & 1 deletion Sources/NostrSDK/EventKind.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,15 @@ public enum EventKind: RawRepresentable, CaseIterable, Codable, Equatable {

/// This kind of note is used to signal to followers that another event is worth reading.
///
/// > Note: The reposted event must be a kind 1 text note.
/// See [NIP-18](https://github.com/nostr-protocol/nips/blob/master/18.md#nip-18).
case repost

/// This kind of note is used to signal to followers that another event is worth reading.
///
/// > Note: The reposted event can be any kind of event other than a kind 1 text note.
/// See [NIP-18](https://github.com/nostr-protocol/nips/blob/master/18.md#nip-18).
case genericRepost

/// Any other event kind number that isn't supported by this enum yet will be represented by `unknown` so that `NostrEvent`s of those event kinds can still be encoded and decoded.
case unknown(RawValue)
Expand All @@ -47,7 +54,8 @@ public enum EventKind: RawRepresentable, CaseIterable, Codable, Equatable {
.textNote,
.recommendServer,
.contactList,
.repost
.repost,
.genericRepost
]

public init(rawValue: Int) {
Expand All @@ -62,6 +70,7 @@ public enum EventKind: RawRepresentable, CaseIterable, Codable, Equatable {
case .recommendServer: return 2
case .contactList: return 3
case .repost: return 6
case .genericRepost: return 16
case let .unknown(value): return value
}
}
Expand Down
37 changes: 37 additions & 0 deletions Sources/NostrSDK/Events/GenericRepostEvent.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//
// GenericRepostEvent.swift
//
//
// Created by Bryan Montz on 8/3/23.
//

import Foundation

/// A generic repost event (kind 16) can include any kind of event inside other than kind 1.
/// > Note: Generic reposts SHOULD contain a `k` tag with the stringified kind number of the reposted event as its value.
/// See [NIP-18](https://github.com/nostr-protocol/nips/blob/master/18.md#generic-reposts).
public class GenericRepostEvent: NostrEvent {
/// The pubkey of the reposted event.
var repostedEventPubkey: String? {
tags.first(where: { $0.name == .pubkey })?.value
}

/// The note that is being reposted.
var repostedEvent: NostrEvent? {
guard let jsonData = content.data(using: .utf8),
let note: NostrEvent = try? JSONDecoder().decode(NostrEvent.self, from: jsonData) else {
return nil
}
return note
}

/// The id of the event that is being reposted.
var repostedEventId: String? {
tags.first(where: { $0.name == .event })?.value
}

/// The relay URL at which to fetch the reposted event.
var repostedEventRelayURL: String? {
tags.first(where: { $0.name == .event })?.otherParameters.first
}
}
23 changes: 23 additions & 0 deletions Sources/NostrSDK/Events/TextNoteRepostEvent.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//
// TextNoteRepostEvent.swift
//
//
// Created by Bryan Montz on 8/3/23.
//

import Foundation

/// A repost is a kind 6 event that is used to signal to followers that a kind 1 text note is worth reading.
///
/// See [NIP-18](https://github.com/nostr-protocol/nips/blob/master/18.md#reposts).
public final class TextNoteRepostEvent: GenericRepostEvent {

/// The note that is being reposted.
var repostedNote: TextNoteEvent? {
guard let jsonData = content.data(using: .utf8),
let note: TextNoteEvent = try? JSONDecoder().decode(TextNoteEvent.self, from: jsonData) else {
return nil
}
return note
}
}
2 changes: 2 additions & 0 deletions Sources/NostrSDK/RelayResponse.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ fileprivate struct EventKindMapper: Decodable { // swiftlint:disable:this pr
case .setMetadata: return SetMetadataEvent.self
case .textNote: return TextNoteEvent.self
case .recommendServer: return RecommendServerEvent.self
case .repost: return TextNoteRepostEvent.self
case .genericRepost: return GenericRepostEvent.self
default: return NostrEvent.self
}
}
Expand Down
23 changes: 22 additions & 1 deletion Tests/NostrSDKTests/EventDecodingTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ final class EventDecodingTests: XCTestCase, FixtureLoading {

func testDecodeRepost() throws {

let event: NostrEvent = try decodeFixture(filename: "repost")
let event: TextNoteRepostEvent = try decodeFixture(filename: "repost")

XCTAssertEqual(event.id, "9353c66d99d600f51b9b1f309b804d2156facd227d643eb513eb8c508498da21")
XCTAssertEqual(event.pubkey, "91c9a5e1a9744114c6fe2d61ae4de82629eaaa0fb52f48288093c7e7e036f832")
Expand All @@ -109,5 +109,26 @@ final class EventDecodingTests: XCTestCase, FixtureLoading {
XCTAssertEqual(event.tags, expectedTags)
XCTAssertTrue(event.content.hasPrefix("{\"pubkey\":\"33eecd2e2fae31f36c0bdb843d43611426ee5c023889f0401c1b8f5008e59689\""))
XCTAssertEqual(event.signature, "8c81d6c5b44f134bdded8f6d20c9d299fcbe3bc9687df14d7516e4781b60a00fa7bb71eb73e29c3ca3bc6da2198710c82f64859f79ea33434cffa4d80c29b1c2")

XCTAssertEqual(event.repostedEventId, "6663efd8ffb35325af90a84cb223dc388e9d355abf7319fe5c4c5ca7f37e9a34")

let repostedNote = try XCTUnwrap(event.repostedNote)
XCTAssertEqual(repostedNote.id, "6663efd8ffb35325af90a84cb223dc388e9d355abf7319fe5c4c5ca7f37e9a34")
XCTAssertEqual(repostedNote.pubkey, "33eecd2e2fae31f36c0bdb843d43611426ee5c023889f0401c1b8f5008e59689")
XCTAssertEqual(repostedNote.createdAt, 1684482315)
}

func testDecodeGenericRepost() throws {

let event: GenericRepostEvent = try decodeFixture(filename: "generic_repost")

XCTAssertEqual(event.repostedEventPubkey, "reposted-event-pubkey")
XCTAssertEqual(event.repostedEventId, "test-id")
XCTAssertEqual(event.repostedEventRelayURL, "wss://reposted.relay")

let repostedEvent = try XCTUnwrap(event.repostedEvent)

XCTAssertEqual(repostedEvent.id, "test-id")
XCTAssertEqual(repostedEvent.kind, .recommendServer)
}
}
19 changes: 19 additions & 0 deletions Tests/NostrSDKTests/Fixtures/generic_repost.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"content": "{\"pubkey\":\"reposted-event-pubkey\",\"content\":\"wss:\/\/relay.test\",\"id\":\"test-id\",\"created_at\":1660947193,\"sig\":\"e46223e4324c910e9325b095093e3e8ef5122e223940b040553893124c66e3afb815599af97cc58f2b93cb240e37c42d75fb7747e896c6d51753b93aefb5f22a\",\"kind\":2,\"tags\":[[\"e\",\"9941b55c2844f275b7b8714a1c39859088a425ce798f740ea8fea879f9098641\"]]}",
"created_at": 1660947401,
"id": "f366fce0c21d201d7a2e3fc25d5a20ab481992ccced7de606965543a66c8643f",
"kind": 16,
"pubkey": "3efdaebb1d8923ebd99c9e7ace3b4194ab45512e2be79c1b7d68d9243e0d2681",
"sig": "8f073e7ba13ad6d4709cac193a6bc6f8d7a1427114cb84547aa5c19af9e804a59a7432fc2669b1e2bf0cf6393243689a8dddb0eaeca754f35d6dc28bc8ca7d16",
"tags": [
[
"e",
"test-id",
"wss://reposted.relay"
],
[
"p",
"reposted-event-pubkey"
]
]
}

0 comments on commit f637ffc

Please sign in to comment.