Browse and listen to thousands of radio stations across the globe right from your terminal ๐ŸŒŽ ๐Ÿ“ป ๐ŸŽตโœจ
radio rust tokio web-radio command-line-tool tui
at main 4.7 kB view raw
1use tunein_cli::{ 2 api::{ 3 objects::v1alpha1::{Category, Station, StationLinkDetails}, 4 tunein::v1alpha1::{ 5 browse_service_server::BrowseService, BrowseCategoryRequest, BrowseCategoryResponse, 6 GetCategoriesRequest, GetCategoriesResponse, GetStationDetailsRequest, 7 GetStationDetailsResponse, SearchRequest, SearchResponse, 8 }, 9 }, 10 provider::radiobrowser::Radiobrowser, 11}; 12 13use tunein_cli::provider::{tunein::Tunein, Provider}; 14 15#[derive(Default)] 16pub struct Browse; 17 18#[tonic::async_trait] 19impl BrowseService for Browse { 20 async fn get_categories( 21 &self, 22 request: tonic::Request<GetCategoriesRequest>, 23 ) -> Result<tonic::Response<GetCategoriesResponse>, tonic::Status> { 24 let req = request.into_inner(); 25 let provider = req.provider.as_deref(); 26 27 let client: Box<dyn Provider + Send + Sync> = match provider { 28 Some("tunein") => Box::new(Tunein::new()), 29 Some("radiobrowser") => Box::new(Radiobrowser::new().await), 30 None => Box::new(Tunein::new()), 31 _ => { 32 return Err(tonic::Status::internal("Unsupported provider")); 33 } 34 }; 35 36 let offset = req.offset.unwrap_or(0); 37 let limit = req.limit.unwrap_or(100); 38 let result = client 39 .categories(offset, limit) 40 .await 41 .map_err(|e| tonic::Status::internal(e.to_string()))?; 42 43 Ok(tonic::Response::new(GetCategoriesResponse { 44 categories: result.into_iter().map(Category::from).collect(), 45 })) 46 } 47 48 async fn browse_category( 49 &self, 50 request: tonic::Request<BrowseCategoryRequest>, 51 ) -> Result<tonic::Response<BrowseCategoryResponse>, tonic::Status> { 52 let req = request.into_inner(); 53 let category_id = req.category_id; 54 55 let offset = req.offset.unwrap_or(0); 56 let limit = req.limit.unwrap_or(100); 57 58 let provider = req.provider.as_deref(); 59 60 let client: Box<dyn Provider + Send + Sync> = match provider { 61 Some("tunein") => Box::new(Tunein::new()), 62 Some("radiobrowser") => Box::new(Radiobrowser::new().await), 63 None => Box::new(Tunein::new()), 64 _ => { 65 return Err(tonic::Status::internal("Unsupported provider")); 66 } 67 }; 68 69 let results = client 70 .browse(category_id, offset, limit) 71 .await 72 .map_err(|e| tonic::Status::internal(e.to_string()))?; 73 74 let categories = results.into_iter().map(Category::from).collect(); 75 Ok(tonic::Response::new(BrowseCategoryResponse { categories })) 76 } 77 78 async fn get_station_details( 79 &self, 80 request: tonic::Request<GetStationDetailsRequest>, 81 ) -> Result<tonic::Response<GetStationDetailsResponse>, tonic::Status> { 82 let req = request.into_inner(); 83 let station_id = req.id; 84 85 let provider = req.provider.as_deref(); 86 87 let client: Box<dyn Provider + Send + Sync> = match provider { 88 Some("tunein") => Box::new(Tunein::new()), 89 Some("radiobrowser") => Box::new(Radiobrowser::new().await), 90 None => Box::new(Tunein::new()), 91 _ => { 92 return Err(tonic::Status::internal("Unsupported provider")); 93 } 94 }; 95 96 let result = client 97 .get_station(station_id) 98 .await 99 .map_err(|e| tonic::Status::internal(e.to_string()))?; 100 101 let station = match result { 102 Some(station) => station, 103 None => return Err(tonic::Status::internal("No station found")), 104 }; 105 Ok(tonic::Response::new(GetStationDetailsResponse { 106 station_link_details: Some(StationLinkDetails::from(station)), 107 })) 108 } 109 110 async fn search( 111 &self, 112 request: tonic::Request<SearchRequest>, 113 ) -> Result<tonic::Response<SearchResponse>, tonic::Status> { 114 let req = request.into_inner(); 115 let provider = req.provider.as_deref(); 116 117 let client: Box<dyn Provider + Send + Sync> = match provider { 118 Some("tunein") => Box::new(Tunein::new()), 119 Some("radiobrowser") => Box::new(Radiobrowser::new().await), 120 None => Box::new(Tunein::new()), 121 _ => { 122 return Err(tonic::Status::internal("Unsupported provider")); 123 } 124 }; 125 126 let results = client 127 .search(req.query) 128 .await 129 .map_err(|e| tonic::Status::internal(e.to_string()))?; 130 let station = results.into_iter().map(Station::from).collect(); 131 Ok(tonic::Response::new(SearchResponse { station })) 132 } 133}