-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathplugin_mod.rs
153 lines (134 loc) · 4.81 KB
/
plugin_mod.rs
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
//! Coffee plugin implementation to use
//! Coffee as a core lightning plugin.
use std::fmt::Display;
use serde::{Deserialize, Serialize};
use serde_json::{json, Value};
use tokio::runtime::Runtime;
use clightningrpc_common::json_utils;
use clightningrpc_plugin::commands::RPCCommand;
use clightningrpc_plugin::error;
use clightningrpc_plugin::plugin::{debug, info};
use clightningrpc_plugin::{errors::PluginError, plugin::Plugin};
use clightningrpc_plugin_macros::{plugin, rpc_method};
use coffee_core::coffee::CoffeeManager;
use coffee_lib::errors::CoffeeError;
use coffee_lib::macros::error as coffee_err;
use coffee_lib::plugin_manager::PluginManager;
use super::model::{InstallReq, RemoteCmd, RemoteReq};
use super::state::PluginArgs;
use crate::plugin::State;
pub fn build_plugin() -> Result<Plugin<State>, PluginError> {
let mut plugin = plugin! {
state: State::new(),
dynamic: true,
notification: [],
methods: [
coffee_install,
coffee_list,
coffee_remote,
coffee_generate_tip,
],
hooks: [],
};
plugin.on_init(on_init);
Ok(plugin)
}
/// on init function is called by the plugin workflow when the
/// init method is sent from core lightning
///
/// This is an interceptor, at this point the plugin configuration and
/// options are already binding with the plugin.
fn on_init(plugin: &mut Plugin<State>) -> Value {
let response = json_utils::init_payload();
let cln_conf = plugin.configuration.clone().unwrap();
let args = PluginArgs::from(cln_conf);
info!("{:?}", args);
plugin.state.set_args(args);
debug!("{:?}", plugin.configuration);
debug!("{:?}", plugin.state.args);
// Get the runtime and start the block function
let runtime = Runtime::new().unwrap();
let result = runtime.block_on(async move {
let coffee = CoffeeManager::new(&plugin.state.args()).await;
if let Err(err) = &coffee {
debug!("{err}");
return Err(coffee_err!("{err}"));
}
let coffee = coffee.unwrap();
plugin.state.set_coffee(coffee);
plugin.state.setup().await
});
if let Err(err) = result {
let err = format!("{err}");
return json!({
"disable": err,
});
}
response
}
fn from<T: Display>(err: T) -> PluginError {
error!("{err}")
}
#[rpc_method(
rpc_name = "coffee_install",
description = "install a plugin from one of the repository choosed"
)]
fn coffee_install(plugin: &mut Plugin<State>, request: Value) -> Result<Value, PluginError> {
let coffee = plugin.state.coffee();
let mut coffee = coffee.lock().unwrap();
let rt = Runtime::new().unwrap();
let request: InstallReq = serde_json::from_value(request)?;
rt.block_on(coffee.install(&request.name, None, false, true))
.map_err(from)?;
Ok(json!({}))
}
#[rpc_method(
rpc_name = "coffee_list",
description = "show all the plugin installed and if {remotes} is specified show also the one available"
)]
fn coffee_list(plugin: &mut Plugin<State>, _: Value) -> Result<Value, PluginError> {
let runtime = Runtime::new().unwrap();
let coffee = plugin.state.coffee();
let mut coffee = coffee.lock().unwrap();
let result = runtime.block_on(coffee.list()).map_err(from)?;
Ok(serde_json::to_value(result)?)
}
#[rpc_method(rpc_name = "coffee_remote", description = "manage a remote")]
fn coffee_remote(plugin: &mut Plugin<State>, request: Value) -> Result<Value, PluginError> {
let request: RemoteReq = serde_json::from_value(request)?;
let runtime = Runtime::new().unwrap();
let coffee = plugin.state.coffee();
runtime
.block_on(async {
let mut coffee = coffee.lock().unwrap();
let cmd = request.cmd().unwrap();
match cmd {
RemoteCmd::Add => coffee.add_remote(&request.name, &request.url()).await,
RemoteCmd::Rm => coffee.rm_remote(&request.name).await,
}
})
.map_err(from)?;
Ok(json!({}))
}
#[rpc_method(
rpc_name = "coffee_generate_tip",
description = "Generate the BOLT 12 to add inside a plugin configuration to receive donation"
)]
fn coffee_generate_tip(plugin: &mut Plugin<State>, request: Value) -> Result<Value, PluginError> {
let runtime = Runtime::new().unwrap();
let coffee = plugin.state.coffee();
#[derive(Serialize, Deserialize, Debug)]
struct Offer {
pub bolt12: String,
}
let offer = runtime
.block_on(async {
let mut coffee = coffee.lock().unwrap();
coffee.cln::<Value, Offer>("offer", json!({
"amount": "any",
"description": "Generating BOLT 12 for coffee tips regarding the plugin ...",
})).await
})
.map_err(from)?;
Ok(serde_json::to_value(offer)?)
}