eeea9d3266
Closes: https://github.com/damus-io/damus/issues/3007 Changelog-Added: Added new onboarding suggestions based on user-selected interests Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
112 lines
3.5 KiB
Swift
112 lines
3.5 KiB
Swift
//
|
|
// InterestList.swift
|
|
// damus
|
|
//
|
|
// Created by Daniel D'Aquino on 2025-06-23.
|
|
//
|
|
// Some text excerpts taken from the Nostr Protocol itself (which are public domain)
|
|
|
|
import Foundation
|
|
|
|
/// Includes models and functions for working with NIP-51
|
|
struct NIP51: Sendable {}
|
|
|
|
extension NIP51 {
|
|
/// An error thrown when decoding an item into a NIP-51 list
|
|
enum NIP51DecodingError: Error {
|
|
/// The Nostr event being converted is not a NIP-51 interest list
|
|
case notInterestList
|
|
}
|
|
}
|
|
|
|
extension NIP51 {
|
|
/// Models a NIP-51 Interest List (kind:10015)
|
|
struct InterestList: NostrEventConvertible, Sendable {
|
|
typealias E = NIP51DecodingError
|
|
|
|
enum InterestItem: Sendable, Hashable {
|
|
case hashtag(String)
|
|
case interestSet(String, String, String) // a-tag: kind, pubkey, identifier
|
|
|
|
var tag: [String] {
|
|
switch self {
|
|
case .hashtag(let tag):
|
|
return ["t", tag]
|
|
case .interestSet(let kind, let pubkey, let identifier):
|
|
var tag = ["a", "\(kind):\(pubkey):\(identifier)"]
|
|
return tag
|
|
}
|
|
}
|
|
|
|
static func fromTag(tag: TagSequence) -> InterestItem? {
|
|
var i = tag.makeIterator()
|
|
|
|
guard let t0 = i.next(),
|
|
let t1 = i.next() else { return nil }
|
|
|
|
let tagName = t0.string()
|
|
|
|
if tagName == "t" {
|
|
return .hashtag(t1.string())
|
|
} else if tagName == "a" {
|
|
let components = t1.string().split(separator: ":")
|
|
guard components.count > 2 else { return nil }
|
|
|
|
let kind = String(components[0])
|
|
let pubkey = String(components[1])
|
|
let identifier = String(components[2])
|
|
|
|
return .interestSet(kind, pubkey, identifier)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
}
|
|
|
|
let interests: [InterestItem]
|
|
|
|
// MARK: - Initialization
|
|
|
|
init(event: NdbNote) throws(E) {
|
|
try self.init(event: UnownedNdbNote(event))
|
|
}
|
|
|
|
init(event: borrowing UnownedNdbNote) throws(E) {
|
|
guard event.known_kind == .interest_list else {
|
|
throw E.notInterestList
|
|
}
|
|
|
|
var interests: [InterestItem] = []
|
|
|
|
for tag in event.tags {
|
|
if let interest = InterestItem.fromTag(tag: tag) {
|
|
interests.append(interest)
|
|
}
|
|
}
|
|
|
|
self.interests = interests
|
|
}
|
|
|
|
init?(event: NdbNote?) throws(E) {
|
|
guard let event else { return nil }
|
|
try self.init(event: event)
|
|
}
|
|
|
|
init(interests: [InterestItem]) {
|
|
self.interests = interests
|
|
}
|
|
|
|
// MARK: - Conversion to a Nostr Event
|
|
|
|
func toNostrEvent(keypair: FullKeypair, timestamp: UInt32? = nil) -> NostrEvent? {
|
|
return NdbNote(
|
|
content: "",
|
|
keypair: keypair.to_keypair(),
|
|
kind: NostrKind.interest_list.rawValue,
|
|
tags: self.interests.map { $0.tag },
|
|
createdAt: timestamp ?? UInt32(Date.now.timeIntervalSince1970)
|
|
)
|
|
}
|
|
}
|
|
}
|