1
1
use async_graphql:: Result ;
2
2
use database:: { MediaLot , MediaSource } ;
3
3
use enum_meta:: HashMap ;
4
- use itertools:: Itertools ;
5
4
use sea_orm:: prelude:: DateTimeUtc ;
6
5
use serde:: { Deserialize , Serialize } ;
7
6
use serde_json:: json;
8
7
use surf:: {
9
- http:: headers:: { ACCEPT , USER_AGENT } ,
8
+ http:: headers:: { ACCEPT , AUTHORIZATION , USER_AGENT } ,
10
9
Client , Config , Url ,
11
10
} ;
12
11
@@ -20,14 +19,8 @@ use crate::{
20
19
utils:: USER_AGENT_STR ,
21
20
} ;
22
21
23
- #[ derive( Debug , Serialize , Deserialize , Clone , Eq , PartialEq ) ]
24
- #[ serde( rename_all = "lowercase" ) ]
25
- enum CollectionType {
26
- Movies ,
27
- Tvshows ,
28
- #[ serde( untagged) ]
29
- Unknown ( String ) ,
30
- }
22
+ static EMBY_HEADER_VALUE : & str =
23
+ r#"MediaBrowser , Client="other", Device="script", DeviceId="script", Version="0.0.0""# ;
31
24
32
25
#[ derive( Debug , Serialize , Deserialize , Clone , Eq , PartialEq ) ]
33
26
enum MediaType {
@@ -47,7 +40,6 @@ struct ItemProviderIdsPayload {
47
40
#[ derive( Serialize , Deserialize , Debug , Clone ) ]
48
41
#[ serde( rename_all = "PascalCase" ) ]
49
42
struct ItemUserData {
50
- play_count : Option < i32 > ,
51
43
last_played_date : Option < DateTimeUtc > ,
52
44
is_favorite : Option < bool > ,
53
45
}
@@ -64,7 +56,6 @@ struct ItemResponse {
64
56
series_name : Option < String > ,
65
57
user_data : Option < ItemUserData > ,
66
58
parent_index_number : Option < i32 > ,
67
- collection_type : Option < CollectionType > ,
68
59
provider_ids : Option < ItemProviderIdsPayload > ,
69
60
}
70
61
@@ -82,19 +73,18 @@ struct AuthenticateResponse {
82
73
}
83
74
84
75
pub async fn import ( input : DeployUrlAndKeyAndUsernameImportInput ) -> Result < ImportResult > {
85
- let authenticate: AuthenticateResponse = surf:: post ( format ! (
86
- "{}/Users/AuthenticateByName" ,
87
- input. api_url
88
- ) )
89
- . header (
90
- "X-Emby-Authorization" ,
91
- r#"MediaBrowser , Client="other", Device="script", DeviceId="script", Version="0.0.0""# ,
92
- )
93
- . body_json ( & serde_json:: json!( { "Username" : input. username, "Pw" : input. password } ) )
94
- . unwrap ( )
95
- . await ?
96
- . body_json ( )
97
- . await ?;
76
+ let uri = format ! ( "{}/Users/AuthenticateByName" , input. api_url) ;
77
+ let authenticate: AuthenticateResponse = surf:: post ( uri)
78
+ . header ( AUTHORIZATION , EMBY_HEADER_VALUE )
79
+ . body_json ( & serde_json:: json!( { "Username" : input. username, "Pw" : input. password } ) )
80
+ . unwrap ( )
81
+ . await
82
+ . unwrap ( )
83
+ . body_json ( )
84
+ . await
85
+ . unwrap ( ) ;
86
+ tracing:: debug!( "Authenticated with token: {}" , authenticate. access_token) ;
87
+
98
88
let client: Client = Config :: new ( )
99
89
. add_header ( USER_AGENT , USER_AGENT_STR )
100
90
. unwrap ( )
@@ -106,12 +96,16 @@ pub async fn import(input: DeployUrlAndKeyAndUsernameImportInput) -> Result<Impo
106
96
. try_into ( )
107
97
. unwrap ( ) ;
108
98
let user_id = authenticate. user . id ;
99
+ tracing:: debug!( "Authenticated as user id: {}" , user_id) ;
109
100
110
101
let mut to_handle_media = vec ! [ ] ;
111
102
let mut failed_items = vec ! [ ] ;
112
103
113
- let views_data: ItemsResponse = client
114
- . get ( & format ! ( "Users/{}/Views" , user_id) )
104
+ let query = json ! ( { "recursive" : true , "IsPlayed" : true , "fields" : "ProviderIds" } ) ;
105
+ let library_data: ItemsResponse = client
106
+ . get ( & format ! ( "Users/{}/Items" , user_id) )
107
+ . query ( & query)
108
+ . unwrap ( )
115
109
. await
116
110
. unwrap ( )
117
111
. body_json ( )
@@ -120,107 +114,77 @@ pub async fn import(input: DeployUrlAndKeyAndUsernameImportInput) -> Result<Impo
120
114
121
115
let mut series_id_to_tmdb_id: HashMap < String , Option < String > > = HashMap :: new ( ) ;
122
116
123
- for library in views_data. items {
124
- let collection_type = library. collection_type . unwrap ( ) ;
125
- if matches ! ( collection_type, CollectionType :: Unknown ( _) ) {
126
- failed_items. push ( ImportFailedItem {
127
- step : ImportFailStep :: ItemDetailsFromSource ,
128
- identifier : library. name ,
129
- error : Some ( format ! ( "Unknown collection type: {:?}" , collection_type) ) ,
130
- lot : None ,
131
- } ) ;
132
- continue ;
133
- }
134
- let query = json ! ( {
135
- "parentId" : library. id, "recursive" : true ,
136
- "IsPlayed" : true , "fields" : "ProviderIds"
137
- } ) ;
138
- let library_data: ItemsResponse = client
139
- . get ( & format ! ( "Users/{}/Items" , user_id) )
140
- . query ( & query)
141
- . unwrap ( )
142
- . await
143
- . unwrap ( )
144
- . body_json ( )
145
- . await
146
- . unwrap ( ) ;
147
- for item in library_data. items {
148
- let typ = item. typ . clone ( ) . unwrap ( ) ;
149
- tracing:: debug!( "Processing item: {:?} ({:?})" , item. name, typ) ;
150
- let ( lot, tmdb_id, ssn, sen) = match typ. clone ( ) {
151
- MediaType :: Movie => ( MediaLot :: Movie , item. provider_ids . unwrap ( ) . tmdb , None , None ) ,
152
- MediaType :: Series | MediaType :: Episode => {
153
- if let Some ( series_id) = item. series_id {
154
- let mut tmdb_id = series_id_to_tmdb_id. get ( & series_id) . cloned ( ) . flatten ( ) ;
155
- if tmdb_id. is_none ( ) {
156
- let details: ItemResponse = client
157
- . get ( & format ! ( "Items/{}" , series_id) )
158
- . await
159
- . unwrap ( )
160
- . body_json ( )
161
- . await
162
- . unwrap ( ) ;
163
- let insert_id = details. provider_ids . unwrap ( ) . tmdb ;
164
- series_id_to_tmdb_id. insert ( series_id. clone ( ) , insert_id. clone ( ) ) ;
165
- tmdb_id = insert_id;
166
- }
167
- (
168
- MediaLot :: Show ,
169
- tmdb_id,
170
- item. parent_index_number ,
171
- item. index_number ,
172
- )
173
- } else {
174
- continue ;
117
+ for item in library_data. items {
118
+ let typ = item. typ . clone ( ) . unwrap ( ) ;
119
+ tracing:: debug!( "Processing item: {:?} ({:?})" , item. name, typ) ;
120
+ let ( lot, tmdb_id, ssn, sen) = match typ. clone ( ) {
121
+ MediaType :: Movie => ( MediaLot :: Movie , item. provider_ids . unwrap ( ) . tmdb , None , None ) ,
122
+ MediaType :: Series | MediaType :: Episode => {
123
+ if let Some ( series_id) = item. series_id {
124
+ let mut tmdb_id = series_id_to_tmdb_id. get ( & series_id) . cloned ( ) . flatten ( ) ;
125
+ if tmdb_id. is_none ( ) {
126
+ let details: ItemResponse = client
127
+ . get ( & format ! ( "Items/{}" , series_id) )
128
+ . await
129
+ . unwrap ( )
130
+ . body_json ( )
131
+ . await
132
+ . unwrap ( ) ;
133
+ let insert_id = details. provider_ids . unwrap ( ) . tmdb ;
134
+ series_id_to_tmdb_id. insert ( series_id. clone ( ) , insert_id. clone ( ) ) ;
135
+ tmdb_id = insert_id;
175
136
}
176
- }
177
- _ => {
178
- failed_items. push ( ImportFailedItem {
179
- step : ImportFailStep :: ItemDetailsFromSource ,
180
- identifier : item. name ,
181
- error : Some ( format ! ( "Unknown media type: {:?}" , typ) ) ,
182
- lot : None ,
183
- } ) ;
137
+ (
138
+ MediaLot :: Show ,
139
+ tmdb_id,
140
+ item. parent_index_number ,
141
+ item. index_number ,
142
+ )
143
+ } else {
184
144
continue ;
185
145
}
186
- } ;
187
- if let Some ( tmdb_id) = tmdb_id {
188
- let item_user_data = item. user_data . unwrap ( ) ;
189
- let num_times_seen = item_user_data. play_count . unwrap_or ( 0 ) ;
190
- let mut seen_history = ( 0 ..num_times_seen)
191
- . map ( |_| ImportOrExportMediaItemSeen {
192
- show_season_number : ssn,
193
- show_episode_number : sen,
194
- ..Default :: default ( )
195
- } )
196
- . collect_vec ( ) ;
197
- if let Some ( last) = seen_history. last_mut ( ) {
198
- last. ended_on = item_user_data. last_played_date ;
199
- } ;
200
- let mut collections = vec ! [ ] ;
201
- if let Some ( true ) = item_user_data. is_favorite {
202
- collections. push ( "Favorites" . to_string ( ) ) ;
203
- }
204
- to_handle_media. push ( ImportOrExportMediaItem {
205
- lot,
206
- source_id : item. series_name . unwrap_or ( item. name ) ,
207
- source : MediaSource :: Tmdb ,
208
- internal_identifier : Some ( ImportOrExportItemIdentifier :: NeedsDetails (
209
- tmdb_id. clone ( ) ,
210
- ) ) ,
211
- seen_history,
212
- identifier : tmdb_id,
213
- reviews : vec ! [ ] ,
214
- collections,
215
- } ) ;
216
- } else {
146
+ }
147
+ _ => {
217
148
failed_items. push ( ImportFailedItem {
218
149
step : ImportFailStep :: ItemDetailsFromSource ,
219
150
identifier : item. name ,
220
- error : Some ( "No tmdb id found" . to_string ( ) ) ,
151
+ error : Some ( format ! ( "Unknown media type: {:?}" , typ ) ) ,
221
152
lot : None ,
222
153
} ) ;
154
+ continue ;
223
155
}
156
+ } ;
157
+ if let Some ( tmdb_id) = tmdb_id {
158
+ let item_user_data = item. user_data . unwrap ( ) ;
159
+ let seen = ImportOrExportMediaItemSeen {
160
+ show_season_number : ssn,
161
+ show_episode_number : sen,
162
+ ended_on : item_user_data. last_played_date . map ( |d| d. date_naive ( ) ) ,
163
+ ..Default :: default ( )
164
+ } ;
165
+ let mut collections = vec ! [ ] ;
166
+ if let Some ( true ) = item_user_data. is_favorite {
167
+ collections. push ( "Favorites" . to_string ( ) ) ;
168
+ }
169
+ to_handle_media. push ( ImportOrExportMediaItem {
170
+ lot,
171
+ source_id : item. series_name . unwrap_or ( item. name ) ,
172
+ source : MediaSource :: Tmdb ,
173
+ internal_identifier : Some ( ImportOrExportItemIdentifier :: NeedsDetails (
174
+ tmdb_id. clone ( ) ,
175
+ ) ) ,
176
+ seen_history : vec ! [ seen] ,
177
+ identifier : tmdb_id,
178
+ reviews : vec ! [ ] ,
179
+ collections,
180
+ } ) ;
181
+ } else {
182
+ failed_items. push ( ImportFailedItem {
183
+ step : ImportFailStep :: ItemDetailsFromSource ,
184
+ identifier : item. name ,
185
+ error : Some ( "No tmdb id found" . to_string ( ) ) ,
186
+ lot : None ,
187
+ } ) ;
224
188
}
225
189
}
226
190
0 commit comments