Skip to content

Commit 4d9bca3

Browse files
committed
progress
1 parent fe7ee73 commit 4d9bca3

File tree

6 files changed

+78
-55
lines changed

6 files changed

+78
-55
lines changed

src-tauri/src/lib.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,8 @@ pub fn run() {
8484
start_restream,
8585
stop_restream,
8686
watch_self,
87-
get_network_info
87+
get_network_info,
88+
share_restream
8889
])
8990
.setup(|app| {
9091
app.manage(Mutex::new(AppState {
@@ -282,7 +283,7 @@ fn add_custom_source(name: String) -> Result<(), String> {
282283

283284
#[tauri::command(async)]
284285
fn share_custom_channel(channel: Channel) -> Result<(), String> {
285-
share::share_custom_channel(channel).map_err(map_err_frontend)
286+
share::share_custom_channel(channel, None).map_err(map_err_frontend)
286287
}
287288

288289
#[tauri::command(async)]
@@ -426,3 +427,8 @@ async fn watch_self(port: u16) -> Result<(), String> {
426427
async fn get_network_info() -> Result<NetworkInfo, String> {
427428
restream::get_network_info().await.map_err(map_err_frontend)
428429
}
430+
431+
#[tauri::command(async)]
432+
fn share_restream(address: String, channel: Channel) -> Result<(), String> {
433+
restream::share_restream(address, channel).map_err(map_err_frontend)
434+
}

src-tauri/src/restream.rs

+17-15
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use std::{
44
};
55

66
use anyhow::{Context, Result};
7-
use if_addrs::IfAddr;
87
use tauri::State;
98
use tokio::{
109
fs,
@@ -150,20 +149,23 @@ pub async fn watch_self(port: u16) -> Result<()> {
150149
mpv::play(channel, false).await
151150
}
152151

153-
fn share_restream(address: String, channel: Channel) -> Result<()> {
154-
crate::share::share_custom_channel(Channel {
155-
id: Some(-1),
156-
name: format!("RST | {}", channel.name).to_string(),
157-
url: Some(address),
158-
group: None,
159-
image: channel.image,
160-
media_type: crate::media_type::LIVESTREAM,
161-
source_id: None,
162-
series_id: None,
163-
group_id: None,
164-
favorite: false,
165-
stream_id: None,
166-
})
152+
pub fn share_restream(address: String, channel: Channel) -> Result<()> {
153+
crate::share::share_custom_channel(
154+
Channel {
155+
id: Some(-1),
156+
name: format!("RST | {}", channel.name).to_string(),
157+
url: Some(address),
158+
group: None,
159+
image: channel.image,
160+
media_type: crate::media_type::LIVESTREAM,
161+
source_id: None,
162+
series_id: None,
163+
group_id: None,
164+
favorite: false,
165+
stream_id: None,
166+
},
167+
Some(format!("RST - {}", channel.id.context("no id")?)),
168+
)
167169
}
168170

169171
pub async fn get_network_info() -> Result<NetworkInfo> {

src-tauri/src/share.rs

+11-6
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::types::ExportedGroup;
33
use crate::types::ExportedSource;
44
use crate::types::Group;
55
use crate::types::Source;
6+
use crate::utils::sanitize;
67
use crate::{sql, types::Channel};
78
use anyhow::bail;
89
use anyhow::Context;
@@ -14,20 +15,21 @@ const CHANNEL_SHARE_EXTENSION: &str = ".otv";
1415
const GROUP_SHARE_EXTENSION: &str = ".otvg";
1516
const PLAYLIST_SHARE_EXTENSION: &str = ".otvp";
1617

17-
pub fn share_custom_channel(channel: Channel) -> Result<()> {
18+
pub fn share_custom_channel(channel: Channel, filename: Option<String>) -> Result<()> {
1819
let channel = get_custom_channel(channel)?;
1920
let path = get_download_path(
20-
channel.data.id.context("No id on channel?")?,
21+
filename.unwrap_or(channel.data.id.context("No id on channel?")?.to_string()),
2122
CHANNEL_SHARE_EXTENSION,
2223
)?;
2324
serialize_to_file(channel, path)
2425
}
2526

26-
fn get_download_path(id: i64, extension: &str) -> Result<String> {
27+
fn get_download_path(filename: String, extension: &str) -> Result<String> {
2728
let path = UserDirs::new().context("No user dirs?")?;
2829
let path = path.download_dir().context("No downloads folder")?;
2930
let mut path = path.to_path_buf();
30-
path.push(format!("{id}{extension}"));
31+
let filename = sanitize(filename);
32+
path.push(format!("{filename}{extension}"));
3133
Ok(path.to_string_lossy().to_string())
3234
}
3335

@@ -54,7 +56,10 @@ pub fn share_custom_group(group: Channel) -> Result<()> {
5456
},
5557
channels: sql::get_custom_channels(group.id, group.source_id.context("no source id?")?)?,
5658
};
57-
let path = get_download_path(group.id.context("No group id?")?, GROUP_SHARE_EXTENSION)?;
59+
let path = get_download_path(
60+
group.id.context("No group id?")?.to_string(),
61+
GROUP_SHARE_EXTENSION,
62+
)?;
5863
serialize_to_file(to_export, path)?;
5964
Ok(())
6065
}
@@ -67,7 +72,7 @@ pub fn share_custom_source(mut source: Source) -> Result<()> {
6772
groups: sql::get_custom_groups(id)?,
6873
channels: sql::get_custom_channels(None, id)?,
6974
};
70-
let path = get_download_path(id, PLAYLIST_SHARE_EXTENSION)?;
75+
let path = get_download_path(id.to_string(), PLAYLIST_SHARE_EXTENSION)?;
7176
serialize_to_file(to_export, path)?;
7277
Ok(())
7378
}

src-tauri/src/utils.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ fn get_filename(channel_name: String, url: String) -> Result<String> {
8181
Ok(filename)
8282
}
8383

84-
fn sanitize(str: String) -> String {
84+
pub fn sanitize(str: String) -> String {
8585
ILLEGAL_CHARS_REGEX.replace_all(&str, "").to_string()
8686
}
8787

src/app/restream-modal/restream-modal.component.html

+23-29
Original file line numberDiff line numberDiff line change
@@ -27,23 +27,22 @@ <h4 class="modal-title lbl">Re-streaming: {{ channel?.name }}</h4>
2727
<div *ngIf="started">
2828
<br />
2929
<p>
30-
Press the share button (Share LAN or Share WAN) below to generate an .otv file for this
31-
service. You will be able to share this file with your friends so they can import it in Open
32-
TV and watch your re-streamed livestream
30+
Select an IP and press the share button below to generate an .otv file. You will be able to
31+
share this file with your friends so they can import it in Open TV and watch your re-streamed
32+
content.
3333
</p>
3434
<br />
3535
<p>
36-
Your re-streaming service is always availaible from your LAN. On the other hand, WAN access
37-
will work if you open the appropriate port on your router (3000 by default)
36+
You can import .otv files in Open TV by having or creating a custom source. Make sure to
37+
select the right IP for the right context; sharing an .otv file with one of your local IPs
38+
will not work for someone outside your LAN.
3839
</p>
3940
<br />
40-
<p>To import an .otv file in Open TV:</p>
41-
<ol>
42-
<li>Create a new custom source (either from setup or settings)</li>
43-
<li>Go in settings</li>
44-
<li>Click on "import channel/group" button within the custom source</li>
45-
<li>Select the .otv file</li>
46-
</ol>
41+
<label for="ip-select">Select IP to share</label>
42+
<select [(ngModel)]="selectedIP" id="ip-select" class="form-control">
43+
<option *ngFor="let local of networkInfo?.local_ips">{{ local }}</option>
44+
<option>{{ networkInfo?.wan_ip }}</option>
45+
</select>
4746
</div>
4847
</div>
4948
<div class="modal-footer">
@@ -79,60 +78,55 @@ <h4 class="modal-title lbl">Re-streaming: {{ channel?.name }}</h4>
7978
</svg>
8079
</button>
8180
<button
82-
ngbTooltip="Sharing over LAN means sharing for your local network. The .otv file generated will
83-
point to your local IP"
8481
class="btn btn-primary d-inline-flex align-items-center"
8582
(click)="share()"
8683
*ngIf="started"
8784
>
88-
<span>Share LAN</span>
85+
<span>Share</span>
8986
<svg
9087
class="icon ms-1"
9188
fill="currentColor"
9289
xmlns="http://www.w3.org/2000/svg"
9390
viewBox="0 0 24 24"
9491
>
9592
<path
96-
d="M10,2C8.89,2 8,2.89 8,4V7C8,8.11 8.89,9 10,9H11V11H2V13H6V15H5C3.89,15 3,15.89 3,17V20C3,21.11 3.89,22 5,22H9C10.11,22 11,21.11 11,20V17C11,15.89 10.11,15 9,15H8V13H16V15H15C13.89,15 13,15.89 13,17V20C13,21.11 13.89,22 15,22H19C20.11,22 21,21.11 21,20V17C21,15.89 20.11,15 19,15H18V13H22V11H13V9H14C15.11,9 16,8.11 16,7V4C16,2.89 15.11,2 14,2H10M10,4H14V7H10V4M5,17H9V20H5V17M15,17H19V20H15V17Z"
93+
d="M12,2A8,8 0 0,0 4,10C4,14.03 7,17.42 11,17.93V19H10A1,1 0 0,0 9,20H2V22H9A1,1 0 0,0 10,23H14A1,1 0 0,0 15,22H22V20H15A1,1 0 0,0 14,19H13V17.93C17,17.43 20,14.03 20,10A8,8 0 0,0 12,2M12,4C12,4 12.74,5.28 13.26,7H10.74C11.26,5.28 12,4 12,4M9.77,4.43C9.5,4.93 9.09,5.84 8.74,7H6.81C7.5,5.84 8.5,4.93 9.77,4.43M14.23,4.44C15.5,4.94 16.5,5.84 17.19,7H15.26C14.91,5.84 14.5,4.93 14.23,4.44M6.09,9H8.32C8.28,9.33 8.25,9.66 8.25,10C8.25,10.34 8.28,10.67 8.32,11H6.09C6.03,10.67 6,10.34 6,10C6,9.66 6.03,9.33 6.09,9M10.32,9H13.68C13.72,9.33 13.75,9.66 13.75,10C13.75,10.34 13.72,10.67 13.68,11H10.32C10.28,10.67 10.25,10.34 10.25,10C10.25,9.66 10.28,9.33 10.32,9M15.68,9H17.91C17.97,9.33 18,9.66 18,10C18,10.34 17.97,10.67 17.91,11H15.68C15.72,10.67 15.75,10.34 15.75,10C15.75,9.66 15.72,9.33 15.68,9M6.81,13H8.74C9.09,14.16 9.5,15.07 9.77,15.56C8.5,15.06 7.5,14.16 6.81,13M10.74,13H13.26C12.74,14.72 12,16 12,16C12,16 11.26,14.72 10.74,13M15.26,13H17.19C16.5,14.16 15.5,15.07 14.23,15.57C14.5,15.07 14.91,14.16 15.26,13Z"
9794
/>
9895
</svg>
9996
</button>
10097
<button
101-
ngbTooltip="Sharing over WAN means sharing for the internet. The .otv file generated will point
102-
to your public IP"
103-
class="btn btn-primary d-inline-flex align-items-center"
104-
(click)="share()"
98+
class="btn btn-danger d-inline-flex align-items-center"
10599
*ngIf="started"
100+
[disabled]="loading"
101+
(click)="stop()"
106102
>
107-
<span>Share WAN</span>
103+
<span>Stop</span>
108104
<svg
109105
class="icon ms-1"
110106
fill="currentColor"
111107
xmlns="http://www.w3.org/2000/svg"
112108
viewBox="0 0 24 24"
113109
>
114110
<path
115-
d="M12,2A8,8 0 0,0 4,10C4,14.03 7,17.42 11,17.93V19H10A1,1 0 0,0 9,20H2V22H9A1,1 0 0,0 10,23H14A1,1 0 0,0 15,22H22V20H15A1,1 0 0,0 14,19H13V17.93C17,17.43 20,14.03 20,10A8,8 0 0,0 12,2M12,4C12,4 12.74,5.28 13.26,7H10.74C11.26,5.28 12,4 12,4M9.77,4.43C9.5,4.93 9.09,5.84 8.74,7H6.81C7.5,5.84 8.5,4.93 9.77,4.43M14.23,4.44C15.5,4.94 16.5,5.84 17.19,7H15.26C14.91,5.84 14.5,4.93 14.23,4.44M6.09,9H8.32C8.28,9.33 8.25,9.66 8.25,10C8.25,10.34 8.28,10.67 8.32,11H6.09C6.03,10.67 6,10.34 6,10C6,9.66 6.03,9.33 6.09,9M10.32,9H13.68C13.72,9.33 13.75,9.66 13.75,10C13.75,10.34 13.72,10.67 13.68,11H10.32C10.28,10.67 10.25,10.34 10.25,10C10.25,9.66 10.28,9.33 10.32,9M15.68,9H17.91C17.97,9.33 18,9.66 18,10C18,10.34 17.97,10.67 17.91,11H15.68C15.72,10.67 15.75,10.34 15.75,10C15.75,9.66 15.72,9.33 15.68,9M6.81,13H8.74C9.09,14.16 9.5,15.07 9.77,15.56C8.5,15.06 7.5,14.16 6.81,13M10.74,13H13.26C12.74,14.72 12,16 12,16C12,16 11.26,14.72 10.74,13M15.26,13H17.19C16.5,14.16 15.5,15.07 14.23,15.57C14.5,15.07 14.91,14.16 15.26,13Z"
111+
d="M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M9,9H15V15H9"
116112
/>
117113
</svg>
118114
</button>
119115
<button
120-
class="btn btn-danger d-inline-flex align-items-center"
121-
*ngIf="started"
122-
[disabled]="loading"
123-
(click)="stop()"
116+
(click)="activeModal.close('close')"
117+
class="btn btn-secondary d-inline-flex align-items-center"
118+
*ngIf="!started"
124119
>
125-
<span>Stop</span>
120+
<span>Close</span>
126121
<svg
127122
class="icon ms-1"
128123
fill="currentColor"
129124
xmlns="http://www.w3.org/2000/svg"
130125
viewBox="0 0 24 24"
131126
>
132127
<path
133-
d="M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M9,9H15V15H9"
128+
d="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z"
134129
/>
135130
</svg>
136131
</button>
137-
<button class="btn btn-secondary d-inline-flex align-items-center" *ngIf="!started">Close</button>
138132
</div>

src/app/restream-modal/restream-modal.component.ts

+18-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Channel } from "../models/channel";
33
import { invoke } from "@tauri-apps/api/core";
44
import { ErrorService } from "../error.service";
55
import { NetworkInfo } from "../models/networkInfo";
6+
import { NgbActiveModal } from "@ng-bootstrap/ng-bootstrap";
67

78
@Component({
89
selector: "app-restream-modal",
@@ -17,11 +18,17 @@ export class RestreamModalComponent implements OnInit {
1718
address = "http://192.168.2.10/stream.m3u8";
1819
wanAddress = "http://10.145.22.12/stream.m3u8";
1920
networkInfo?: NetworkInfo;
20-
constructor(private error: ErrorService) {}
21+
selectedIP?: string;
22+
23+
constructor(
24+
private error: ErrorService,
25+
public activeModal: NgbActiveModal,
26+
) {}
2127

2228
ngOnInit(): void {
2329
invoke("get_network_info").then((network) => {
2430
this.networkInfo = network as NetworkInfo;
31+
this.selectedIP = this.networkInfo.local_ips[0];
2532
});
2633
}
2734

@@ -59,5 +66,14 @@ export class RestreamModalComponent implements OnInit {
5966
this.watching = false;
6067
}
6168

62-
share() {}
69+
async share() {
70+
try {
71+
await invoke("share_restream", { address: this.selectedIP, channel: this.channel });
72+
this.error.success(
73+
`Successfully exported re-stream to Downloads/rst-${this.channel?.id}.otv`,
74+
);
75+
} catch (e) {
76+
this.error.handleError(e);
77+
}
78+
}
6379
}

0 commit comments

Comments
 (0)