feat: update rust nostr
This commit is contained in:
41
src-tauri/capabilities/main.json
Normal file
41
src-tauri/capabilities/main.json
Normal file
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"$schema": "../gen/schemas/desktop-schema.json",
|
||||
"identifier": "desktop-capability",
|
||||
"description": "Capability for the desktop",
|
||||
"platforms": ["linux", "macOS", "windows"],
|
||||
"windows": ["main", "settings", "event-*", "user-*", "column-*"],
|
||||
"permissions": [
|
||||
"path:default",
|
||||
"event:default",
|
||||
"window:default",
|
||||
"app:default",
|
||||
"resources:default",
|
||||
"menu:default",
|
||||
"tray:default",
|
||||
"theme:allow-set-theme",
|
||||
"theme:allow-get-theme",
|
||||
"notification:allow-is-permission-granted",
|
||||
"notification:allow-request-permission",
|
||||
"notification:default",
|
||||
"os:allow-locale",
|
||||
{
|
||||
"identifier": "http:default",
|
||||
"allow": [
|
||||
{
|
||||
"url": "http://**/"
|
||||
},
|
||||
{
|
||||
"url": "https://**/"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-read-text-file",
|
||||
"allow": [
|
||||
{
|
||||
"path": "$RESOURCE/locales/*"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
{
|
||||
"$schema": "./schemas/desktop-schema.json",
|
||||
"identifier": "desktop-capability",
|
||||
"description": "Capability for the desktop",
|
||||
"platforms": ["linux", "macOS", "windows"],
|
||||
"windows": ["main", "settings", "event-*", "user-*", "column-*"],
|
||||
"permissions": [
|
||||
"path:default",
|
||||
"event:default",
|
||||
"window:default",
|
||||
"app:default",
|
||||
"resources:default",
|
||||
"menu:default",
|
||||
"tray:default",
|
||||
"shell:open",
|
||||
"theme:allow-set-theme",
|
||||
"theme:allow-get-theme",
|
||||
"notification:allow-is-permission-granted",
|
||||
"notification:allow-request-permission",
|
||||
"notification:allow-notify",
|
||||
{
|
||||
"identifier": "http:default",
|
||||
"allow": [
|
||||
{
|
||||
"url": "http://**/"
|
||||
},
|
||||
{
|
||||
"url": "https://**/"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:scope",
|
||||
"allow": [
|
||||
{
|
||||
"path": "$APPDATA/*"
|
||||
},
|
||||
{
|
||||
"path": "$LOCALDATA/*"
|
||||
},
|
||||
{
|
||||
"path": "$DESKTOP/*"
|
||||
},
|
||||
{
|
||||
"path": "$DOCUMENT/*"
|
||||
},
|
||||
{
|
||||
"path": "$DOWNLOAD/*"
|
||||
},
|
||||
{
|
||||
"path": "$HOME/*"
|
||||
},
|
||||
{
|
||||
"path": "$PICTURE/*"
|
||||
},
|
||||
{
|
||||
"path": "$PUBLIC/*"
|
||||
},
|
||||
{
|
||||
"path": "$VIDEO/*"
|
||||
},
|
||||
{
|
||||
"path": "$RESOURCE"
|
||||
},
|
||||
{
|
||||
"path": "$RESOURCE/*"
|
||||
},
|
||||
{
|
||||
"path": "$RESOURCE/locales/*"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
{}
|
||||
{"desktop-capability":{"identifier":"desktop-capability","description":"Capability for the desktop","context":"local","windows":["main","settings","event-*","user-*","column-*"],"permissions":["path:default","event:default","window:default","app:default","resources:default","menu:default","tray:default","theme:allow-set-theme","theme:allow-get-theme","notification:allow-is-permission-granted","notification:allow-request-permission","notification:default","os:allow-locale",{"identifier":"http:default","allow":[{"url":"http://**/"},{"url":"https://**/"}]},{"identifier":"fs:allow-read-text-file","allow":[{"path":"$RESOURCE/locales/*"}]}],"platforms":["linux","macOS","windows"]}}
|
||||
@@ -13,11 +13,13 @@ use db::api::v1::Account;
|
||||
use keyring::Entry;
|
||||
use nostr_sdk::prelude::*;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use tauri::Manager;
|
||||
use tauri_plugin_autostart::MacosLauncher;
|
||||
|
||||
pub struct Nostr {
|
||||
pub client: Arc<Client>,
|
||||
pub contact_list: Option<Vec<Contact>>,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
@@ -28,7 +30,7 @@ fn main() {
|
||||
let config_dir = handle.path().app_config_dir().unwrap();
|
||||
|
||||
tauri::async_runtime::spawn(async move {
|
||||
// Create database connection
|
||||
// Create nostr database connection
|
||||
let nostr_db = SQLiteDatabase::open(config_dir.join("nostr.db"))
|
||||
.await
|
||||
.expect("Open database failed.");
|
||||
@@ -36,40 +38,18 @@ fn main() {
|
||||
// Create nostr connection
|
||||
let client = ClientBuilder::default().database(nostr_db).build();
|
||||
|
||||
// create app database connection
|
||||
// Create app database connection
|
||||
let db = DATABASE_BUILDER
|
||||
.create(config_dir.join("app.db"))
|
||||
.expect("failed to create app database");
|
||||
|
||||
// run db migrate
|
||||
// Run migration for app database
|
||||
let rw = db
|
||||
.rw_transaction()
|
||||
.expect("failed to create rw migration transaction");
|
||||
rw.migrate::<Account>().expect("failed to migrate Account");
|
||||
rw.commit().expect("failed to commit migration");
|
||||
|
||||
// get stored account
|
||||
let r = db.r_transaction().expect("failed to create ro transaction");
|
||||
let accounts: Vec<Account> = r
|
||||
.scan()
|
||||
.secondary(AccountKey::status)
|
||||
.expect("failed to scan accounts")
|
||||
.start_with("active")
|
||||
.collect();
|
||||
|
||||
if let Some(account) = accounts.into_iter().nth(0) {
|
||||
let entry = Entry::new("Lume", &account.pubkey).expect("failed to load secret");
|
||||
|
||||
if let Ok(key) = entry.get_password() {
|
||||
let secret_key = SecretKey::from_bech32(key).unwrap();
|
||||
let keys = Keys::new(secret_key);
|
||||
let signer = ClientSigner::Keys(keys);
|
||||
|
||||
// update client's signer
|
||||
client.set_signer(Some(signer)).await;
|
||||
}
|
||||
}
|
||||
|
||||
// Add some bootstrap relays
|
||||
// #TODO: Pull bootstrap relays from user's settings
|
||||
client
|
||||
@@ -84,9 +64,43 @@ fn main() {
|
||||
// Connect
|
||||
client.connect().await;
|
||||
|
||||
// Get stored account
|
||||
let r = db.r_transaction().expect("failed to create ro transaction");
|
||||
let accounts: Vec<Account> = r
|
||||
.scan()
|
||||
.secondary(AccountKey::status)
|
||||
.expect("failed to scan accounts")
|
||||
.start_with("active")
|
||||
.collect();
|
||||
let mut contact_list = None;
|
||||
|
||||
// Run somethings if account existed
|
||||
if let Some(account) = accounts.into_iter().nth(0) {
|
||||
// Add signer with stored private key
|
||||
let entry = Entry::new("Lume", &account.pubkey).expect("failed to load secret");
|
||||
|
||||
if let Ok(key) = entry.get_password() {
|
||||
let secret_key = SecretKey::from_bech32(key).unwrap();
|
||||
let keys = Keys::new(secret_key);
|
||||
let signer = ClientSigner::Keys(keys);
|
||||
|
||||
// Update client's signer
|
||||
client.set_signer(Some(signer)).await;
|
||||
|
||||
// Get contact list
|
||||
contact_list = Some(
|
||||
client
|
||||
.get_contact_list(Some(Duration::from_secs(10)))
|
||||
.await
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Init global state
|
||||
handle.manage(Nostr {
|
||||
client: client.into(),
|
||||
contact_list: contact_list.into(),
|
||||
})
|
||||
});
|
||||
|
||||
@@ -113,6 +127,8 @@ fn main() {
|
||||
nostr::keys::get_public_key,
|
||||
nostr::keys::update_signer,
|
||||
nostr::keys::verify_signer,
|
||||
nostr::keys::event_to_bech32,
|
||||
nostr::keys::user_to_bech32,
|
||||
nostr::metadata::get_metadata,
|
||||
nostr::event::get_event,
|
||||
commands::secret::secure_save,
|
||||
|
||||
@@ -4,17 +4,26 @@ use std::time::Duration;
|
||||
use tauri::State;
|
||||
|
||||
#[tauri::command(async)]
|
||||
pub async fn get_event(id: String, nostr: State<'_, Nostr>) -> Result<String, ()> {
|
||||
pub async fn get_event(id: &str, nostr: State<'_, Nostr>) -> Result<String, ()> {
|
||||
let client = &nostr.client;
|
||||
let event_id;
|
||||
|
||||
if id.starts_with("note1") {
|
||||
event_id = EventId::from_bech32(id).unwrap();
|
||||
} else if id.starts_with("nevent1") {
|
||||
event_id = EventId::from_bech32(id).unwrap();
|
||||
} else if id.starts_with("naddr1") {
|
||||
event_id = EventId::from_bech32(id).unwrap();
|
||||
} else {
|
||||
event_id = EventId::from_hex(id).unwrap();
|
||||
}
|
||||
|
||||
let event_id = EventId::from_bech32(id).unwrap();
|
||||
let filter = Filter::new().id(event_id);
|
||||
|
||||
let events = client
|
||||
.get_events_of(vec![filter], Some(Duration::from_secs(10)))
|
||||
.await
|
||||
.expect("Get metadata failed");
|
||||
let event = events.into_iter().nth(0).unwrap().as_json();
|
||||
.expect("Get event failed");
|
||||
let event = events.first().unwrap().as_json();
|
||||
|
||||
Ok(event)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::Nostr;
|
||||
use nostr_sdk::prelude::*;
|
||||
use std::str::FromStr;
|
||||
use tauri::State;
|
||||
|
||||
#[derive(serde::Serialize)]
|
||||
@@ -23,15 +24,16 @@ pub fn create_keys() -> Result<CreateKeysResponse, ()> {
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn get_public_key(secret_key: SecretKey) -> Result<String, ()> {
|
||||
pub fn get_public_key(nsec: String) -> Result<String, ()> {
|
||||
let secret_key = SecretKey::from_bech32(nsec).unwrap();
|
||||
let keys = Keys::new(secret_key);
|
||||
Ok(keys.public_key().to_bech32().expect("secret key failed"))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn update_signer(key: String, nostr: State<'_, Nostr>) -> Result<(), ()> {
|
||||
pub async fn update_signer(nsec: String, nostr: State<'_, Nostr>) -> Result<(), ()> {
|
||||
let client = &nostr.client;
|
||||
let secret_key = SecretKey::from_bech32(key).unwrap();
|
||||
let secret_key = SecretKey::from_bech32(nsec).unwrap();
|
||||
let keys = Keys::new(secret_key);
|
||||
let signer = ClientSigner::Keys(keys);
|
||||
|
||||
@@ -47,3 +49,19 @@ pub async fn verify_signer(nostr: State<'_, Nostr>) -> Result<bool, ()> {
|
||||
|
||||
Ok(status)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn event_to_bech32(id: &str, relays: Vec<String>) -> Result<String, ()> {
|
||||
let event_id = EventId::from_hex(id).unwrap();
|
||||
let event = Nip19Event::new(event_id, relays);
|
||||
|
||||
Ok(event.to_bech32().unwrap())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn user_to_bech32(key: &str, relays: Vec<String>) -> Result<String, ()> {
|
||||
let pubkey = XOnlyPublicKey::from_str(key).unwrap();
|
||||
let profile = Nip19Profile::new(pubkey, relays);
|
||||
|
||||
Ok(profile.to_bech32().unwrap())
|
||||
}
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
use crate::Nostr;
|
||||
use nostr_sdk::prelude::*;
|
||||
use std::time::Duration;
|
||||
use std::{str::FromStr, time::Duration};
|
||||
use tauri::State;
|
||||
|
||||
#[tauri::command(async)]
|
||||
pub async fn get_metadata(npub: String, nostr: State<'_, Nostr>) -> Result<Metadata, ()> {
|
||||
pub async fn get_metadata(id: &str, nostr: State<'_, Nostr>) -> Result<Metadata, ()> {
|
||||
let client = &nostr.client;
|
||||
let public_key;
|
||||
|
||||
let public_key = XOnlyPublicKey::from_bech32(npub).unwrap();
|
||||
if id.starts_with("nprofile1") {
|
||||
public_key = XOnlyPublicKey::from_bech32(id).unwrap();
|
||||
} else if id.starts_with("npub1") {
|
||||
public_key = XOnlyPublicKey::from_bech32(id).unwrap();
|
||||
} else {
|
||||
public_key = XOnlyPublicKey::from_str(id).unwrap();
|
||||
}
|
||||
|
||||
let filter = Filter::new()
|
||||
.author(public_key)
|
||||
@@ -19,7 +26,7 @@ pub async fn get_metadata(npub: String, nostr: State<'_, Nostr>) -> Result<Metad
|
||||
.await
|
||||
.expect("Get metadata failed");
|
||||
|
||||
let event = events.into_iter().nth(0).unwrap();
|
||||
let event = events.first().unwrap();
|
||||
let metadata: Metadata = Metadata::from_json(&event.content).unwrap();
|
||||
|
||||
Ok(metadata)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"build": {
|
||||
"beforeBuildCommand": "pnpm run build",
|
||||
"beforeDevCommand": "pnpm desktop:dev",
|
||||
"devUrl": "http://localhost:5173",
|
||||
"devUrl": "http://localhost:3000",
|
||||
"frontendDist": "../dist"
|
||||
},
|
||||
"app": {
|
||||
@@ -42,10 +42,7 @@
|
||||
"targets": "all",
|
||||
"active": true,
|
||||
"category": "SocialNetworking",
|
||||
"resources": [
|
||||
"resources/*",
|
||||
"./locales/*"
|
||||
],
|
||||
"resources": ["resources/*", "./locales/*"],
|
||||
"icon": [
|
||||
"icons/32x32.png",
|
||||
"icons/128x128.png",
|
||||
|
||||
Reference in New Issue
Block a user