1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
use async_std::net::TcpStream;
use kuska_handshake::async_std::BoxStream;
use kuska_sodiumoxide::crypto::{auth, sign::ed25519};
use kuska_ssb::{
api::ApiCaller,
discovery, keystore,
keystore::OwnedIdentity,
rpc::{RpcReader, RpcWriter},
};
use crate::error::GolgiError;
pub struct SbotConnection {
pub client: ApiCaller<TcpStream>,
pub rpc_reader: RpcReader<TcpStream>,
}
pub struct Sbot {
pub id: String,
public_key: ed25519::PublicKey,
private_key: ed25519::SecretKey,
address: String,
network_id: auth::Key,
}
impl Sbot {
pub async fn init(ip_port: Option<String>, net_id: Option<String>) -> Result<Sbot, GolgiError> {
let address = if ip_port.is_none() {
"127.0.0.1:8008".to_string()
} else {
ip_port.unwrap()
};
let network_id = if net_id.is_none() {
discovery::ssb_net_id()
} else {
auth::Key::from_slice(&hex::decode(net_id.unwrap()).unwrap()).unwrap()
};
let OwnedIdentity { pk, sk, id } = keystore::from_gosbot_local()
.await
.expect("couldn't read local secret");
Ok(Self {
id,
public_key: pk,
private_key: sk,
address,
network_id,
})
}
pub async fn get_sbot_connection(&self) -> Result<SbotConnection, GolgiError> {
let address = self.address.clone();
let network_id = self.network_id.clone();
let public_key = self.public_key;
let private_key = self.private_key.clone();
Sbot::_get_sbot_connection_helper(address, network_id, public_key, private_key).await
}
async fn _get_sbot_connection_helper(
address: String,
network_id: auth::Key,
public_key: ed25519::PublicKey,
private_key: ed25519::SecretKey,
) -> Result<SbotConnection, GolgiError> {
let socket = TcpStream::connect(&address)
.await
.map_err(|source| GolgiError::Io {
source,
context: "failed to initiate tcp stream connection".to_string(),
})?;
let handshake = kuska_handshake::async_std::handshake_client(
&mut &socket,
network_id.clone(),
public_key,
private_key.clone(),
public_key,
)
.await
.map_err(GolgiError::Handshake)?;
let (box_stream_read, box_stream_write) =
BoxStream::from_handshake(socket.clone(), socket, handshake, 0x8000).split_read_write();
let rpc_reader = RpcReader::new(box_stream_read);
let client = ApiCaller::new(RpcWriter::new(box_stream_write));
let sbot_connection = SbotConnection { rpc_reader, client };
Ok(sbot_connection)
}
}