+21
README.md
+21
README.md
···
146
146
tunein play s221580
147
147
```
148
148
149
+
## ๐ง Systemd Service
150
+
151
+
Tunein daemon can be started as a systemd service. To enable and start the service, run the following command:
152
+
153
+
```bash
154
+
tunein service install
155
+
```
156
+
157
+
To disable and stop the service, run the following command:
158
+
159
+
```bash
160
+
tunein service uninstall
161
+
```
162
+
163
+
To check the status of the service, run the following command:
164
+
165
+
```bash
166
+
tunein service status
167
+
```
168
+
169
+
149
170
## API Documentation
150
171
[https://buf.build/tsiry/tuneinserverapis/docs/main:tunein.v1alpha1](https://buf.build/tsiry/tuneinserverapis/docs/main:tunein.v1alpha1)
151
172
+26
src/main.rs
+26
src/main.rs
···
13
13
mod provider;
14
14
mod search;
15
15
mod server;
16
+
mod service;
16
17
mod tags;
17
18
mod tui;
18
19
mod types;
···
58
59
.about("Start the server")
59
60
.arg(arg!([port] "The port to listen on").default_value("8090")),
60
61
)
62
+
.subcommand(
63
+
Command::new("service")
64
+
.about("Manage systemd service for tunein-cli server")
65
+
.subcommand(
66
+
Command::new("install")
67
+
.about("Install systemd service for tunein-cli server")
68
+
)
69
+
.subcommand(
70
+
Command::new("uninstall")
71
+
.about("Uninstall systemd service for tunein-cli server")
72
+
)
73
+
.subcommand(
74
+
Command::new("status")
75
+
.about("Check status of tunein-cli systemd service")
76
+
)
77
+
)
61
78
}
62
79
63
80
#[tokio::main]
···
93
110
let port = port.parse::<u16>().unwrap();
94
111
server::exec(port).await?;
95
112
}
113
+
Some(("service", sub_m)) => match sub_m.subcommand() {
114
+
Some(("install", _)) => service::install()?,
115
+
Some(("uninstall", _)) => service::uninstall()?,
116
+
Some(("status", _)) => service::status()?,
117
+
_ => {
118
+
println!("Invalid subcommand. Use `tunein service --help` for more information");
119
+
std::process::exit(1);
120
+
}
121
+
},
96
122
_ => unreachable!(),
97
123
}
98
124
+11
src/server/mod.rs
+11
src/server/mod.rs
···
15
15
16
16
pub async fn exec(port: u16) -> Result<(), Error> {
17
17
let addr: SocketAddr = format!("0.0.0.0:{}", port).parse().unwrap();
18
+
println!(
19
+
"{}",
20
+
r#"
21
+
______ ____ _______ ____
22
+
/_ __/_ _____ ___ / _/__ / ___/ / / _/
23
+
/ / / // / _ \/ -_)/ // _ \ / /__/ /___/ /
24
+
/_/ \_,_/_//_/\__/___/_//_/ \___/____/___/
25
+
26
+
"#
27
+
.bright_green()
28
+
);
18
29
println!("Listening on {}", addr.cyan());
19
30
Server::builder()
20
31
.accept_http1(true)
+111
src/service.rs
+111
src/service.rs
···
1
+
use std::{path::Path, process::Command};
2
+
3
+
use anyhow::Error;
4
+
5
+
const SERVICE_TEMPLATE: &str = include_str!("./systemd/tunein.service");
6
+
7
+
pub fn install() -> Result<(), Error> {
8
+
if cfg!(not(target_os = "linux")) {
9
+
println!("This command is only supported on Linux");
10
+
std::process::exit(1);
11
+
}
12
+
13
+
let home = std::env::var("HOME")?;
14
+
let service_path: &str = &format!("{}/.config/systemd/user/tunein.service", home);
15
+
std::fs::create_dir_all(format!("{}/.config/systemd/user", home))
16
+
.expect("Failed to create systemd user directory");
17
+
18
+
if Path::new(service_path).exists() {
19
+
println!("Service file already exists. Nothing to install.");
20
+
return Ok(());
21
+
}
22
+
23
+
let tunein_path = std::env::current_exe()?;
24
+
25
+
let service_template: &str = &SERVICE_TEMPLATE.replace(
26
+
"ExecStart=/usr/bin/tunein",
27
+
&format!("ExecStart={}", tunein_path.display()),
28
+
);
29
+
30
+
std::fs::write(service_path, service_template).expect("Failed to write service file");
31
+
32
+
Command::new("systemctl")
33
+
.arg("--user")
34
+
.arg("daemon-reload")
35
+
.status()?;
36
+
37
+
Command::new("systemctl")
38
+
.arg("--user")
39
+
.arg("enable")
40
+
.arg("tunein")
41
+
.status()?;
42
+
43
+
Command::new("systemctl")
44
+
.arg("--user")
45
+
.arg("start")
46
+
.arg("tunein")
47
+
.status()?;
48
+
49
+
println!("โ
Tunein service installed successfully!");
50
+
51
+
Ok(())
52
+
}
53
+
54
+
pub fn uninstall() -> Result<(), Error> {
55
+
if cfg!(not(target_os = "linux")) {
56
+
println!("This command is only supported on Linux");
57
+
std::process::exit(1);
58
+
}
59
+
60
+
let home = std::env::var("HOME")?;
61
+
let service_path: &str = &format!("{}/.config/systemd/user/tunein.service", home);
62
+
63
+
if Path::new(service_path).exists() {
64
+
Command::new("systemctl")
65
+
.arg("--user")
66
+
.arg("stop")
67
+
.arg("tunein")
68
+
.status()?;
69
+
70
+
Command::new("systemctl")
71
+
.arg("--user")
72
+
.arg("disable")
73
+
.arg("tunein")
74
+
.status()?;
75
+
76
+
std::fs::remove_file(service_path).expect("Failed to remove service file");
77
+
78
+
Command::new("systemctl")
79
+
.arg("--user")
80
+
.arg("daemon-reload")
81
+
.status()?;
82
+
83
+
println!("โ
Tunein service uninstalled successfully!");
84
+
} else {
85
+
println!("Service file does not exist. Nothing to uninstall.");
86
+
}
87
+
88
+
Ok(())
89
+
}
90
+
91
+
pub fn status() -> Result<(), Error> {
92
+
if cfg!(not(target_os = "linux")) {
93
+
println!("This command is only supported on Linux");
94
+
std::process::exit(1);
95
+
}
96
+
97
+
let home = std::env::var("HOME")?;
98
+
let service_path: &str = &format!("{}/.config/systemd/user/tunein.service", home);
99
+
100
+
if Path::new(service_path).exists() {
101
+
Command::new("systemctl")
102
+
.arg("--user")
103
+
.arg("status")
104
+
.arg("tunein")
105
+
.status()?;
106
+
} else {
107
+
println!("Service file does not exist. Tunein service is not installed.");
108
+
}
109
+
110
+
Ok(())
111
+
}