2021-02-08 11:29:27 +01:00
//
// A P I S e r v i c e + F a v o r i t e . s w i f t
// M a s t o d o n
//
// C r e a t e d b y s x i a o j i a n o n 2 0 2 1 / 2 / 8 .
//
import Foundation
import Combine
import MastodonSDK
import CoreData
import CoreDataStack
import CommonOSLog
extension APIService {
// m a k e l o c a l s t a t e c h a n g e o n l y
func like (
tootObjectID : NSManagedObjectID ,
mastodonUserObjectID : NSManagedObjectID ,
favoriteKind : Mastodon . API . Favorites . FavoriteKind
) -> AnyPublisher < Toot . ID , Error > {
var _targetTootID : Toot . ID ?
let managedObjectContext = backgroundManagedObjectContext
return managedObjectContext . performChanges {
let toot = managedObjectContext . object ( with : tootObjectID ) as ! Toot
let mastodonUser = managedObjectContext . object ( with : mastodonUserObjectID ) as ! MastodonUser
let targetToot = toot . reblog ? ? toot
let targetTootID = targetToot . id
_targetTootID = targetTootID
targetToot . update ( liked : favoriteKind = = . create , mastodonUser : mastodonUser )
}
. tryMap { result in
switch result {
case . success :
guard let targetTootID = _targetTootID else {
throw APIError . implicit ( . badRequest )
}
return targetTootID
case . failure ( let error ) :
assertionFailure ( error . localizedDescription )
throw error
}
}
. eraseToAnyPublisher ( )
}
// s e n d f a v o r i t e r e q u e s t t o r e m o t e
func like (
statusID : Mastodon . Entity . Status . ID ,
favoriteKind : Mastodon . API . Favorites . FavoriteKind ,
mastodonAuthenticationBox : AuthenticationService . MastodonAuthenticationBox
) -> AnyPublisher < Mastodon . Response . Content < Mastodon . Entity . Status > , Error > {
let authorization = mastodonAuthenticationBox . userAuthorization
let requestMastodonUserID = mastodonAuthenticationBox . userID
return Mastodon . API . Favorites . favorites ( domain : mastodonAuthenticationBox . domain , statusID : statusID , session : session , authorization : authorization , favoriteKind : favoriteKind )
. map { response -> AnyPublisher < Mastodon . Response . Content < Mastodon . Entity . Status > , Error > in
let log = OSLog . api
let entity = response . value
let managedObjectContext = self . backgroundManagedObjectContext
return managedObjectContext . performChanges {
let _requestMastodonUser : MastodonUser ? = {
let request = MastodonUser . sortedFetchRequest
request . predicate = MastodonUser . predicate ( domain : mastodonAuthenticationBox . domain , id : requestMastodonUserID )
request . fetchLimit = 1
request . returnsObjectsAsFaults = false
do {
return try managedObjectContext . fetch ( request ) . first
} catch {
assertionFailure ( error . localizedDescription )
return nil
}
} ( )
let _oldToot : Toot ? = {
let request = Toot . sortedFetchRequest
request . predicate = Toot . predicate ( domain : mastodonAuthenticationBox . domain , id : entity . id )
request . returnsObjectsAsFaults = false
request . relationshipKeyPathsForPrefetching = [ # keyPath ( Toot . reblog ) ]
do {
return try managedObjectContext . fetch ( request ) . first
} catch {
assertionFailure ( error . localizedDescription )
return nil
}
} ( )
guard let requestMastodonUser = _requestMastodonUser ,
let oldToot = _oldToot else {
assertionFailure ( )
return
}
APIService . CoreData . mergeToot ( for : requestMastodonUser , old : oldToot , in : mastodonAuthenticationBox . domain , entity : entity , networkDate : response . networkDate )
os_log ( . info , log : log , " %{public}s[%{public}ld], %{public}s: did update toot %{public}s like status to: %{public}s. now %ld likes " , ( ( #file as NSString ) . lastPathComponent ) , #line , #function , entity . id , entity . favourited . flatMap { $0 ? " like " : " unlike " } ? ? " <nil> " , entity . favouritesCount )
}
. setFailureType ( to : Error . self )
. tryMap { result -> Mastodon . Response . Content < Mastodon . Entity . Status > in
switch result {
case . success :
return response
case . failure ( let error ) :
throw error
}
}
. eraseToAnyPublisher ( )
}
. switchToLatest ( )
. handleEvents ( receiveCompletion : { completion in
switch completion {
case . failure ( let error ) :
print ( error )
case . finished :
break
}
} )
. eraseToAnyPublisher ( )
}
}
extension APIService {
func likeList (
2021-02-18 05:49:24 +01:00
limit : Int = onceRequestTootMaxCount ,
2021-02-08 11:29:27 +01:00
userID : String ,
maxID : String ? = nil ,
mastodonAuthenticationBox : AuthenticationService . MastodonAuthenticationBox
) -> AnyPublisher < Mastodon . Response . Content < [ Mastodon . Entity . Status ] > , Error > {
let requestMastodonUserID = mastodonAuthenticationBox . userID
let query = Mastodon . API . Favorites . ListQuery ( limit : limit , minID : nil , maxID : maxID )
return Mastodon . API . Favorites . getFavoriteStatus ( domain : mastodonAuthenticationBox . domain , session : session , authorization : mastodonAuthenticationBox . userAuthorization , query : query )
. map { response -> AnyPublisher < Mastodon . Response . Content < [ Mastodon . Entity . Status ] > , Error > in
let log = OSLog . api
return APIService . Persist . persistTimeline (
managedObjectContext : self . backgroundManagedObjectContext ,
domain : mastodonAuthenticationBox . domain ,
2021-02-24 11:40:47 +01:00
query : query ,
2021-02-08 11:29:27 +01:00
response : response ,
persistType : . likeList ,
requestMastodonUserID : requestMastodonUserID ,
log : log
)
. setFailureType ( to : Error . self )
. tryMap { result -> Mastodon . Response . Content < [ Mastodon . Entity . Status ] > in
switch result {
case . success :
return response
case . failure ( let error ) :
throw error
}
}
. eraseToAnyPublisher ( )
}
. switchToLatest ( )
. eraseToAnyPublisher ( )
}
}