···11# Changelog
2233## Next
44+- Add support for `/user/` URLs
45- Fix some errors not being shown
56- Fix notification identifiers
67- Scroll to bottom after adding channel
+17
src-tauri/src/api.rs
···4343 Err("No video returned".to_string())
4444}
45454646+pub async fn channel_id_from_username(username: &str, key: &str) -> Result<String, String> {
4747+ let url = "https://youtube.googleapis.com/youtube/v3/channels".to_string()
4848+ + "?part=contentDetails,id,snippet"
4949+ + "&forUsername="
5050+ + username;
5151+ let channels = yt_request::<channels::Response>(&url, key)
5252+ .await
5353+ .map_err(|e| format!("Failed to get video: {}", e))?;
5454+ if channels.items.len() > 1 {
5555+ return Err("YouTube username search returned in multiple channels".to_string());
5656+ }
5757+ if let Some(channel) = channels.items.first() {
5858+ return Ok(channel.id.clone());
5959+ }
6060+ Err("No video returned".to_string())
6161+}
6262+4663pub mod channels {
4764 use serde::Deserialize;
4865
+15
src-tauri/src/data.rs
···157157 }
158158 Some(path_segments.next()?.to_string())
159159}
160160+fn url_parse_username(value: &str) -> Option<String> {
161161+ let url = Url::parse(value).ok()?;
162162+ let host = url.host_str()?;
163163+ if !host.ends_with("youtube.com") {
164164+ return None;
165165+ }
166166+ let mut path_segments = url.path_segments()?;
167167+ if path_segments.next()? != "user" {
168168+ return None;
169169+ }
170170+ Some(path_segments.next()?.to_string())
171171+}
160172161173#[command]
162174#[specta::specta]
···179191 api::channel_id_from_video_id(&video_id, key).await?
180192 } else if let Some(id) = url_parse_channel_id(&options.url) {
181193 id
194194+ } else if let Some(username) = url_parse_username(&options.url) {
195195+ let key = &settings.api_key_or_default();
196196+ api::channel_id_from_username(&username, key).await?
182197 } else {
183198 return Err(invalid);
184199 };