music_player_server/
library.rs1use futures::future::FutureExt;
2use music_player_entity::{album, artist, artist_tracks, track};
3use music_player_scanner::scan_directory;
4use music_player_storage::repo::artist::ArtistRepository;
5use music_player_storage::repo::track::TrackRepository;
6use music_player_storage::Database;
7use music_player_storage::{repo::album::AlbumRepository, searcher::Searcher};
8use sea_orm::ActiveModelTrait;
9use std::sync::Arc;
10use tokio::sync::Mutex;
11
12use crate::api::music::v1alpha1::{
13 library_service_server::LibraryService, GetAlbumDetailsRequest, GetAlbumDetailsResponse,
14 GetAlbumsRequest, GetAlbumsResponse, GetArtistDetailsRequest, GetArtistDetailsResponse,
15 GetArtistsRequest, GetArtistsResponse, GetTrackDetailsRequest, GetTrackDetailsResponse,
16 GetTracksRequest, GetTracksResponse, ScanRequest, ScanResponse, SearchRequest, SearchResponse,
17};
18
19pub struct Library {
20 db: Database,
21}
22
23impl Library {
24 pub fn new(db: Database) -> Self {
25 Self { db }
26 }
27}
28
29#[tonic::async_trait]
30impl LibraryService for Library {
31 async fn scan(
32 &self,
33 _request: tonic::Request<ScanRequest>,
34 ) -> Result<tonic::Response<ScanResponse>, tonic::Status> {
35 scan_directory(
36 move |song, db| {
37 async move {
38 let item: artist::ActiveModel = song.try_into().unwrap();
39 match item.insert(db.get_connection()).await {
40 Ok(_) => (),
41 Err(_) => (),
42 }
43
44 let item: album::ActiveModel = song.try_into().unwrap();
45 match item.insert(db.get_connection()).await {
46 Ok(_) => (),
47 Err(_) => (),
48 }
49
50 let item: track::ActiveModel = song.try_into().unwrap();
51
52 match item.insert(db.get_connection()).await {
53 Ok(_) => (),
54 Err(_) => (),
55 }
56
57 let item: artist_tracks::ActiveModel = song.try_into().unwrap();
58 match item.insert(db.get_connection()).await {
59 Ok(_) => (),
60 Err(_) => (),
61 }
62 }
63 .boxed()
64 },
65 &Database::new().await,
66 &Searcher::new(),
67 )
68 .await
69 .map_err(|e| tonic::Status::internal(e.to_string()))?;
70
71 let response = ScanResponse {};
72 Ok(tonic::Response::new(response))
73 }
74
75 async fn search(
76 &self,
77 _request: tonic::Request<SearchRequest>,
78 ) -> Result<tonic::Response<SearchResponse>, tonic::Status> {
79 let response = SearchResponse {};
80 Ok(tonic::Response::new(response))
81 }
82
83 async fn get_artists(
84 &self,
85 request: tonic::Request<GetArtistsRequest>,
86 ) -> Result<tonic::Response<GetArtistsResponse>, tonic::Status> {
87 let request = request.into_inner();
88 let filter = match request.filter.as_str() {
89 "" => None,
90 _ => Some(request.filter),
91 };
92 let offset = request.offset;
93 let limit = request.limit;
94 let results = ArtistRepository::new(&self.db.get_connection())
95 .find_all(filter, Some(offset as u64), Some(limit as u64))
96 .await
97 .map_err(|e| tonic::Status::internal(e.to_string()))?;
98
99 let response = GetArtistsResponse {
100 artists: results.into_iter().map(Into::into).collect(),
101 };
102 Ok(tonic::Response::new(response))
103 }
104
105 async fn get_albums(
106 &self,
107 request: tonic::Request<GetAlbumsRequest>,
108 ) -> Result<tonic::Response<GetAlbumsResponse>, tonic::Status> {
109 let request = request.into_inner();
110 let filter = match request.filter.as_str() {
111 "" => None,
112 _ => Some(request.filter),
113 };
114 let offset = request.offset;
115 let limit = request.limit;
116 let results = AlbumRepository::new(&self.db.get_connection())
117 .find_all(filter, Some(offset as u64), Some(limit as u64))
118 .await
119 .map_err(|e| tonic::Status::internal(e.to_string()))?;
120
121 let response = GetAlbumsResponse {
122 albums: results.into_iter().map(Into::into).collect(),
123 };
124 Ok(tonic::Response::new(response))
125 }
126
127 async fn get_tracks(
128 &self,
129 request: tonic::Request<GetTracksRequest>,
130 ) -> Result<tonic::Response<GetTracksResponse>, tonic::Status> {
131 let request = request.into_inner();
132 let filter = match request.filter.as_str() {
133 "" => None,
134 _ => Some(request.filter),
135 };
136 let offset = request.offset;
137 let limit = match request.limit {
138 0 => 100,
139 _ => request.limit,
140 };
141 let tracks = TrackRepository::new(&self.db.get_connection())
142 .find_all(filter, Some(offset as u64), limit as u64)
143 .await
144 .map_err(|e| tonic::Status::internal(e.to_string()))?;
145
146 let response = GetTracksResponse {
147 tracks: tracks.into_iter().map(Into::into).collect(),
148 };
149 Ok(tonic::Response::new(response))
150 }
151
152 async fn get_track_details(
153 &self,
154 request: tonic::Request<GetTrackDetailsRequest>,
155 ) -> Result<tonic::Response<GetTrackDetailsResponse>, tonic::Status> {
156 let id = request.into_inner().id;
157
158 let track = TrackRepository::new(&self.db.get_connection())
159 .find(&id)
160 .await
161 .map_err(|e| tonic::Status::internal(e.to_string()))?;
162
163 Ok(tonic::Response::new(GetTrackDetailsResponse {
164 track: Some(track.into()),
165 }))
166 }
167
168 async fn get_album_details(
169 &self,
170 request: tonic::Request<GetAlbumDetailsRequest>,
171 ) -> Result<tonic::Response<GetAlbumDetailsResponse>, tonic::Status> {
172 let id = request.into_inner().id;
173 let album = AlbumRepository::new(&self.db.get_connection())
174 .find(&id)
175 .await
176 .map_err(|e| tonic::Status::internal(e.to_string()))?;
177
178 Ok(tonic::Response::new(GetAlbumDetailsResponse {
179 album: Some(album.into()),
180 }))
181 }
182
183 async fn get_artist_details(
184 &self,
185 request: tonic::Request<GetArtistDetailsRequest>,
186 ) -> Result<tonic::Response<GetArtistDetailsResponse>, tonic::Status> {
187 let id = request.into_inner().id;
188
189 let artist = ArtistRepository::new(&self.db.get_connection())
190 .find(&id)
191 .await
192 .map_err(|e| tonic::Status::internal(e.to_string()))?;
193
194 let response = GetArtistDetailsResponse {
195 artist: Some(artist.into()),
196 };
197 Ok(tonic::Response::new(response))
198 }
199}