parent
d8c90cb105
commit
f8aa20eb5c
@ -0,0 +1,132 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
/// Represents a Nostr user profile (metadata from kind 0 events).
|
||||||
|
class NostrProfile {
|
||||||
|
/// Public key (npub or hex).
|
||||||
|
final String publicKey;
|
||||||
|
|
||||||
|
/// Display name or username.
|
||||||
|
final String? name;
|
||||||
|
|
||||||
|
/// About/bio text.
|
||||||
|
final String? about;
|
||||||
|
|
||||||
|
/// Profile picture URL.
|
||||||
|
final String? picture;
|
||||||
|
|
||||||
|
/// Website URL.
|
||||||
|
final String? website;
|
||||||
|
|
||||||
|
/// NIP-05 identifier (e.g., user@domain.com).
|
||||||
|
final String? nip05;
|
||||||
|
|
||||||
|
/// Banner image URL.
|
||||||
|
final String? banner;
|
||||||
|
|
||||||
|
/// LUD16 (Lightning address).
|
||||||
|
final String? lud16;
|
||||||
|
|
||||||
|
/// Raw metadata JSON for additional fields.
|
||||||
|
final Map<String, dynamic> rawMetadata;
|
||||||
|
|
||||||
|
/// Timestamp when profile was last updated.
|
||||||
|
final DateTime? updatedAt;
|
||||||
|
|
||||||
|
/// Creates a [NostrProfile] instance.
|
||||||
|
NostrProfile({
|
||||||
|
required this.publicKey,
|
||||||
|
this.name,
|
||||||
|
this.about,
|
||||||
|
this.picture,
|
||||||
|
this.website,
|
||||||
|
this.nip05,
|
||||||
|
this.banner,
|
||||||
|
this.lud16,
|
||||||
|
Map<String, dynamic>? rawMetadata,
|
||||||
|
this.updatedAt,
|
||||||
|
}) : rawMetadata = rawMetadata ?? {};
|
||||||
|
|
||||||
|
/// Creates a [NostrProfile] from Nostr metadata event content (JSON string).
|
||||||
|
///
|
||||||
|
/// [publicKey] - The public key of the profile owner.
|
||||||
|
/// [content] - JSON string from kind 0 event content.
|
||||||
|
/// [updatedAt] - Optional timestamp when profile was updated.
|
||||||
|
factory NostrProfile.fromEventContent({
|
||||||
|
required String publicKey,
|
||||||
|
required String content,
|
||||||
|
DateTime? updatedAt,
|
||||||
|
}) {
|
||||||
|
try {
|
||||||
|
final metadata = jsonDecode(content) as Map<String, dynamic>;
|
||||||
|
|
||||||
|
return NostrProfile(
|
||||||
|
publicKey: publicKey,
|
||||||
|
name: metadata['name'] as String?,
|
||||||
|
about: metadata['about'] as String?,
|
||||||
|
picture: metadata['picture'] as String?,
|
||||||
|
website: metadata['website'] as String?,
|
||||||
|
nip05: metadata['nip05'] as String?,
|
||||||
|
banner: metadata['banner'] as String?,
|
||||||
|
lud16: metadata['lud16'] as String?,
|
||||||
|
rawMetadata: metadata,
|
||||||
|
updatedAt: updatedAt ?? DateTime.now(),
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
// Return minimal profile if parsing fails
|
||||||
|
return NostrProfile(
|
||||||
|
publicKey: publicKey,
|
||||||
|
rawMetadata: {},
|
||||||
|
updatedAt: updatedAt ?? DateTime.now(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a [NostrProfile] from a JSON map.
|
||||||
|
factory NostrProfile.fromJson(Map<String, dynamic> json) {
|
||||||
|
return NostrProfile(
|
||||||
|
publicKey: json['publicKey'] as String,
|
||||||
|
name: json['name'] as String?,
|
||||||
|
about: json['about'] as String?,
|
||||||
|
picture: json['picture'] as String?,
|
||||||
|
website: json['website'] as String?,
|
||||||
|
nip05: json['nip05'] as String?,
|
||||||
|
banner: json['banner'] as String?,
|
||||||
|
lud16: json['lud16'] as String?,
|
||||||
|
rawMetadata: json['rawMetadata'] as Map<String, dynamic>? ?? {},
|
||||||
|
updatedAt: json['updatedAt'] != null
|
||||||
|
? DateTime.parse(json['updatedAt'] as String)
|
||||||
|
: null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts [NostrProfile] to JSON.
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return {
|
||||||
|
'publicKey': publicKey,
|
||||||
|
'name': name,
|
||||||
|
'about': about,
|
||||||
|
'picture': picture,
|
||||||
|
'website': website,
|
||||||
|
'nip05': nip05,
|
||||||
|
'banner': banner,
|
||||||
|
'lud16': lud16,
|
||||||
|
'rawMetadata': rawMetadata,
|
||||||
|
'updatedAt': updatedAt?.toIso8601String(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets display name (name, nip05, or public key prefix).
|
||||||
|
String get displayName {
|
||||||
|
if (name != null && name!.isNotEmpty) return name!;
|
||||||
|
if (nip05 != null && nip05!.isNotEmpty) return nip05!;
|
||||||
|
return publicKey.length > 16
|
||||||
|
? '${publicKey.substring(0, 8)}...${publicKey.substring(publicKey.length - 8)}'
|
||||||
|
: publicKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'NostrProfile(publicKey: ${publicKey.substring(0, 8)}..., name: $name)';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Loading…
Reference in new issue