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,
authenticationBox: MastodonAuthenticationBox
) 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 blockContext: MastodonBlockContext = try await managedObjectContext.performChanges {
// let authentication = authenticationBox.authentication
//
// guard
// let user = user.object(in: managedObjectContext),
// let me = authentication.user(in: managedObjectContext)
// else {
// throw APIError.implicit(.badRequest)
// }
//
// let isBlocking = user.blockingBy.contains(me)
// let isFollowing = user.followingBy.contains(me)
// // toggle block state
// user.update(isBlocking: !isBlocking, by: me)
// // update follow state implicitly
// if !isBlocking {
// // will do block action. set to unfollow
// user.update(isFollowing: false, by: me)
// }
//
// 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
let response: Mastodon.Response.Content<Mastodon.Entity.Relationship>
if relationship.blocking {
response = try await Mastodon.API.Account.unblock(
session: session,
domain: authenticationBox.domain,
accountID: user.id,
authorization: authenticationBox.userAuthorization
).singleOutput()
} else {
response = try await Mastodon.API.Account.block(
session: session,
domain: authenticationBox.domain,
accountID: user.id,
authorization: authenticationBox.userAuthorization
).singleOutput()
}
return response
}
}
extension MastodonUser {

View File

@ -117,94 +117,32 @@ extension APIService {
user: Mastodon.Entity.Account,
authenticationBox: MastodonAuthenticationBox
) async throws -> Mastodon.Response.Content<Mastodon.Entity.Relationship> {
fatalError("Not implemented yet")
/**
1. Get relation between me and user
2. check if I follow them:
if so: unfollow
if not: follow
3. return result of 2.
guard let relationship = try await relationship(forAccounts: [user], authenticationBox: authenticationBox).value.first else {
throw APIError.implicit(.badRequest)
}
*/
let response: Mastodon.Response.Content<Mastodon.Entity.Relationship>
// let managedObjectContext = backgroundManagedObjectContext
// let _followContext: MastodonFollowContext? = try await managedObjectContext.performChanges {
// guard let me = authenticationBox.authentication.user(in: managedObjectContext) else { return nil }
// guard let user = user.object(in: managedObjectContext) else { return nil }
//
// let isFollowing = user.followingBy.contains(me)
// let isPending = user.followRequestedBy.contains(me)
// let needsUnfollow = isFollowing || isPending
//
// if needsUnfollow {
// // unfollow
// user.update(isFollowing: false, by: me)
// user.update(isFollowRequested: false, by: me)
// } else {
// // follow
// if user.locked {
// user.update(isFollowing: false, by: me)
// user.update(isFollowRequested: true, by: me)
// } else {
// 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
if relationship.following || (relationship.requested ?? false) {
// unfollow
response = try await Mastodon.API.Account.unfollow(
session: session,
domain: authenticationBox.domain,
accountID: user.id,
authorization: authenticationBox.userAuthorization
).singleOutput()
} else {
response = try await Mastodon.API.Account.follow(
session: session,
domain: authenticationBox.domain,
accountID: user.id,
followQueryType: .follow(query: .init()),
authorization: authenticationBox.userAuthorization
).singleOutput()
}
return response
}
public func toggleShowReblogs(

View File

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