2021-03-09 08:18:43 +01:00
//
// A P I S e r v i c e + R e b l o g . s w i f t
// M a s t o d o n
//
// C r e a t e d b y M a i n a s u K C i r n o o n 2 0 2 1 - 3 - 9 .
//
import Foundation
import Combine
import MastodonSDK
import CoreData
import CoreDataStack
import CommonOSLog
extension APIService {
2022-01-27 14:23:39 +01:00
private struct MastodonReblogContext {
let statusID : Status . ID
let isReblogged : Bool
let rebloggedCount : Int64
}
2021-03-15 11:19:45 +01:00
func reblog (
2022-01-27 14:23:39 +01:00
record : ManagedObjectRecord < Status > ,
authenticationBox : MastodonAuthenticationBox
) async throws -> Mastodon . Response . Content < Mastodon . Entity . Status > {
let logger = Logger ( subsystem : " APIService " , category : " Reblog " )
2021-03-09 08:18:43 +01:00
let managedObjectContext = backgroundManagedObjectContext
2022-01-27 14:23:39 +01:00
// u p d a t e r e p o s t s t a t e a n d r e t r i e v e r e p o s t c o n t e x t
let _reblogContext : MastodonReblogContext ? = try await managedObjectContext . performChanges {
guard let authentication = authenticationBox . authenticationRecord . object ( in : managedObjectContext ) ,
let _status = record . object ( in : managedObjectContext )
else { return nil }
2021-06-17 10:44:57 +02:00
2022-01-27 14:23:39 +01:00
let me = authentication . user
let status = _status . reblog ? ? _status
let isReblogged = status . rebloggedBy . contains ( me )
let rebloggedCount = status . reblogsCount
let reblogCount = isReblogged ? rebloggedCount - 1 : rebloggedCount + 1
status . update ( reblogged : ! isReblogged , by : me )
status . update ( reblogsCount : Int64 ( max ( 0 , reblogCount ) ) )
let reblogContext = MastodonReblogContext (
statusID : status . id ,
isReblogged : isReblogged ,
rebloggedCount : rebloggedCount
)
logger . log ( level : . debug , " \( ( #file as NSString ) . lastPathComponent , privacy : . public ) [ \( #line , privacy : . public ) ], \( #function , privacy : . public ) : update status reblog: \( ! isReblogged ) , \( reblogCount ) " )
return reblogContext
2021-03-09 08:18:43 +01:00
}
2022-01-27 14:23:39 +01:00
guard let reblogContext = _reblogContext else {
throw APIError . implicit ( . badRequest )
2021-03-09 08:18:43 +01:00
}
2022-01-27 14:23:39 +01:00
// r e q u e s t r e p o s t o r u n d o r e p o s t
let result : Result < Mastodon . Response . Content < Mastodon . Entity . Status > , Error >
do {
let response = try await Mastodon . API . Reblog . reblog (
session : session ,
domain : authenticationBox . domain ,
statusID : reblogContext . statusID ,
reblogKind : reblogContext . isReblogged ? . undoReblog : . reblog ( query : Mastodon . API . Reblog . ReblogQuery ( visibility : . public ) ) ,
authorization : authenticationBox . userAuthorization
) . singleOutput ( )
result = . success ( response )
} catch {
result = . failure ( error )
logger . log ( level : . debug , " \( ( #file as NSString ) . lastPathComponent , privacy : . public ) [ \( #line , privacy : . public ) ], \( #function , privacy : . public ) : update reblog failure: \( error . localizedDescription ) " )
}
// u p d a t e r e p o s t s t a t e
try await managedObjectContext . performChanges {
guard let authentication = authenticationBox . authenticationRecord . object ( in : managedObjectContext ) ,
let _status = record . object ( in : managedObjectContext )
else { return }
let me = authentication . user
let status = _status . reblog ? ? _status
switch result {
case . success ( let response ) :
_ = Persistence . Status . createOrMerge (
in : managedObjectContext ,
context : Persistence . Status . PersistContext (
domain : authentication . domain ,
entity : response . value ,
me : me ,
statusCache : nil ,
userCache : nil ,
networkDate : response . networkDate
)
)
if reblogContext . isReblogged {
status . update ( reblogsCount : max ( 0 , status . reblogsCount - 1 ) ) // u n d o A P I r e t u r n c o u n t h a s d e l a y . N e e d s - 1 l o c a l
2021-03-09 08:18:43 +01:00
}
2022-01-27 14:23:39 +01:00
logger . log ( level : . debug , " \( ( #file as NSString ) . lastPathComponent , privacy : . public ) [ \( #line , privacy : . public ) ], \( #function , privacy : . public ) : update status reblog: \( ! reblogContext . isReblogged ) " )
case . failure :
// r o l l b a c k
status . update ( reblogged : reblogContext . isReblogged , by : me )
status . update ( reblogsCount : reblogContext . rebloggedCount )
logger . log ( level : . debug , " \( ( #file as NSString ) . lastPathComponent , privacy : . public ) [ \( #line , privacy : . public ) ], \( #function , privacy : . public ) : rollback status reblog " )
2021-03-09 08:18:43 +01:00
}
}
2022-01-27 14:23:39 +01:00
let response = try result . get ( )
return response
2021-03-09 08:18:43 +01:00
}
}