Implement follow/unfollow and block/unblock for `Mastodon.Entity.Account`

This commit is contained in:
Nathan Mattes 2023-10-19 15:12:24 +02:00
parent b92ffe8a46
commit 1750ef83a6
3 changed files with 72 additions and 175 deletions

View File

@ -153,93 +153,30 @@ extension APIService {
user: Mastodon.Entity.Account, user: Mastodon.Entity.Account,
authenticationBox: MastodonAuthenticationBox authenticationBox: MastodonAuthenticationBox
) async throws -> Mastodon.Response.Content<Mastodon.Entity.Relationship> { ) async throws -> Mastodon.Response.Content<Mastodon.Entity.Relationship> {
fatalError("Not implemented yet") guard let relationship = try await relationship(forAccounts: [user], authenticationBox: authenticationBox).value.first else {
throw APIError.implicit(.badRequest)
}
// let managedObjectContext = backgroundManagedObjectContext let response: Mastodon.Response.Content<Mastodon.Entity.Relationship>
// let blockContext: MastodonBlockContext = try await managedObjectContext.performChanges {
// let authentication = authenticationBox.authentication if relationship.blocking {
// response = try await Mastodon.API.Account.unblock(
// guard session: session,
// let user = user.object(in: managedObjectContext), domain: authenticationBox.domain,
// let me = authentication.user(in: managedObjectContext) accountID: user.id,
// else { authorization: authenticationBox.userAuthorization
// throw APIError.implicit(.badRequest) ).singleOutput()
// } } else {
// response = try await Mastodon.API.Account.block(
// let isBlocking = user.blockingBy.contains(me) session: session,
// let isFollowing = user.followingBy.contains(me) domain: authenticationBox.domain,
// // toggle block state accountID: user.id,
// user.update(isBlocking: !isBlocking, by: me) authorization: authenticationBox.userAuthorization
// // update follow state implicitly ).singleOutput()
// if !isBlocking { }
// // will do block action. set to unfollow
// user.update(isFollowing: false, by: me) return response
// }
//
// return MastodonBlockContext(
// sourceUserID: me.id,
// targetUserID: user.id,
// targetUsername: user.username,
// isBlocking: isBlocking,
// isFollowing: isFollowing
// )
// }
//
// let result: Result<Mastodon.Response.Content<Mastodon.Entity.Relationship>, Error>
// do {
// if blockContext.isBlocking {
// let response = try await Mastodon.API.Account.unblock(
// session: session,
// domain: authenticationBox.domain,
// accountID: blockContext.targetUserID,
// authorization: authenticationBox.userAuthorization
// ).singleOutput()
// result = .success(response)
// } else {
// let response = try await Mastodon.API.Account.block(
// session: session,
// domain: authenticationBox.domain,
// accountID: blockContext.targetUserID,
// authorization: authenticationBox.userAuthorization
// ).singleOutput()
// result = .success(response)
// }
// } catch {
// result = .failure(error)
// }
//
// try await managedObjectContext.performChanges {
// let authentication = authenticationBox.authentication
//
// guard
// let user = user.object(in: managedObjectContext),
// let me = authentication.user(in: managedObjectContext)
// else { return }
//
//
// switch result {
// case .success(let response):
// let relationship = response.value
// Persistence.MastodonUser.update(
// mastodonUser: user,
// context: Persistence.MastodonUser.RelationshipContext(
// entity: relationship,
// me: me,
// networkDate: response.networkDate
// )
// )
// case .failure:
// // rollback
// user.update(isBlocking: blockContext.isBlocking, by: me)
// user.update(isFollowing: blockContext.isFollowing, by: me)
// }
// }
//
// let response = try result.get()
// return response
} }
} }
extension MastodonUser { extension MastodonUser {

View File

@ -117,94 +117,32 @@ extension APIService {
user: Mastodon.Entity.Account, user: Mastodon.Entity.Account,
authenticationBox: MastodonAuthenticationBox authenticationBox: MastodonAuthenticationBox
) async throws -> Mastodon.Response.Content<Mastodon.Entity.Relationship> { ) async throws -> Mastodon.Response.Content<Mastodon.Entity.Relationship> {
fatalError("Not implemented yet")
/** guard let relationship = try await relationship(forAccounts: [user], authenticationBox: authenticationBox).value.first else {
1. Get relation between me and user throw APIError.implicit(.badRequest)
2. check if I follow them: }
if so: unfollow
if not: follow
3. return result of 2.
*/ let response: Mastodon.Response.Content<Mastodon.Entity.Relationship>
// let managedObjectContext = backgroundManagedObjectContext if relationship.following || (relationship.requested ?? false) {
// let _followContext: MastodonFollowContext? = try await managedObjectContext.performChanges { // unfollow
// guard let me = authenticationBox.authentication.user(in: managedObjectContext) else { return nil } response = try await Mastodon.API.Account.unfollow(
// guard let user = user.object(in: managedObjectContext) else { return nil } session: session,
// domain: authenticationBox.domain,
// let isFollowing = user.followingBy.contains(me) accountID: user.id,
// let isPending = user.followRequestedBy.contains(me) authorization: authenticationBox.userAuthorization
// let needsUnfollow = isFollowing || isPending ).singleOutput()
// } else {
// if needsUnfollow { response = try await Mastodon.API.Account.follow(
// // unfollow session: session,
// user.update(isFollowing: false, by: me) domain: authenticationBox.domain,
// user.update(isFollowRequested: false, by: me) accountID: user.id,
// } else { followQueryType: .follow(query: .init()),
// // follow authorization: authenticationBox.userAuthorization
// if user.locked { ).singleOutput()
// user.update(isFollowing: false, by: me) }
// user.update(isFollowRequested: true, by: me)
// } else { return response
// user.update(isFollowing: true, by: me)
// user.update(isFollowRequested: false, by: me)
// }
// }
// let context = MastodonFollowContext(
// sourceUserID: me.id,
// targetUserID: user.id,
// isFollowing: isFollowing,
// isPending: isPending,
// needsUnfollow: needsUnfollow
// )
// return context
// }
//
// guard let followContext = _followContext else {
// throw APIError.implicit(.badRequest)
// }
//
// // request follow or unfollow
// let result: Result<Mastodon.Response.Content<Mastodon.Entity.Relationship>, Error>
// do {
// let response = try await Mastodon.API.Account.follow(
// session: session,
// domain: authenticationBox.domain,
// accountID: followContext.targetUserID,
// followQueryType: followContext.needsUnfollow ? .unfollow : .follow(query: .init()),
// authorization: authenticationBox.userAuthorization
// ).singleOutput()
// result = .success(response)
// } catch {
// result = .failure(error)
// }
//
// // update friendship state
// try await managedObjectContext.performChanges {
// guard let me = authenticationBox.authentication.user(in: managedObjectContext),
// let user = user.object(in: managedObjectContext)
// else { return }
//
// switch result {
// case .success(let response):
// Persistence.MastodonUser.update(
// mastodonUser: user,
// context: Persistence.MastodonUser.RelationshipContext(
// entity: response.value,
// me: me,
// networkDate: response.networkDate
// )
// )
// case .failure:
// // rollback
// user.update(isFollowing: followContext.isFollowing, by: me)
// user.update(isFollowRequested: followContext.isPending, by: me)
// }
// }
//
// let response = try result.get()
// return response
} }
public func toggleShowReblogs( public func toggleShowReblogs(

View File

@ -18,7 +18,7 @@ extension APIService {
authenticationBox: MastodonAuthenticationBox authenticationBox: MastodonAuthenticationBox
) async throws -> Mastodon.Response.Content<[Mastodon.Entity.Relationship]> { ) async throws -> Mastodon.Response.Content<[Mastodon.Entity.Relationship]> {
let managedObjectContext = backgroundManagedObjectContext let managedObjectContext = backgroundManagedObjectContext
let _query: Mastodon.API.Account.RelationshipQuery? = try? await managedObjectContext.perform { let _query: Mastodon.API.Account.RelationshipQuery? = try? await managedObjectContext.perform {
var ids: [MastodonUser.ID] = [] var ids: [MastodonUser.ID] = []
for record in records { for record in records {
@ -32,14 +32,14 @@ extension APIService {
guard let query = _query else { guard let query = _query else {
throw APIError.implicit(.badRequest) throw APIError.implicit(.badRequest)
} }
let response = try await Mastodon.API.Account.relationships( let response = try await Mastodon.API.Account.relationships(
session: session, session: session,
domain: authenticationBox.domain, domain: authenticationBox.domain,
query: query, query: query,
authorization: authenticationBox.userAuthorization authorization: authenticationBox.userAuthorization
).singleOutput() ).singleOutput()
try await managedObjectContext.performChanges { try await managedObjectContext.performChanges {
guard let me = authenticationBox.authentication.user(in: managedObjectContext) else { guard let me = authenticationBox.authentication.user(in: managedObjectContext) else {
// assertionFailure() // assertionFailure()
@ -50,7 +50,7 @@ extension APIService {
for record in records { for record in records {
guard let user = record.object(in: managedObjectContext) else { continue } guard let user = record.object(in: managedObjectContext) else { continue }
guard let relationship = relationships.first(where: { $0.id == user.id }) else { continue } guard let relationship = relationships.first(where: { $0.id == user.id }) else { continue }
Persistence.MastodonUser.update( Persistence.MastodonUser.update(
mastodonUser: user, mastodonUser: user,
context: Persistence.MastodonUser.RelationshipContext( context: Persistence.MastodonUser.RelationshipContext(
@ -64,5 +64,27 @@ extension APIService {
return response return response
} }
public func relationship(
forAccounts accounts: [Mastodon.Entity.Account],
authenticationBox: MastodonAuthenticationBox
) async throws -> Mastodon.Response.Content<[Mastodon.Entity.Relationship]> {
let ids: [MastodonUser.ID] = accounts.compactMap { $0.id }
guard ids.isEmpty == false else { throw APIError.implicit(.badRequest) }
let query = Mastodon.API.Account.RelationshipQuery(ids: ids)
let response = try await Mastodon.API.Account.relationships(
session: session,
domain: authenticationBox.domain,
query: query,
authorization: authenticationBox.userAuthorization
).singleOutput()
return response
}
} }