Skip to content

Instantly share code, notes, and snippets.

@saroar
Last active November 12, 2020 20:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save saroar/2578797f5fa53a10d061243957ad12c3 to your computer and use it in GitHub Desktop.
Save saroar/2578797f5fa53a10d061243957ad12c3 to your computer and use it in GitHub Desktop.
Save Contacts and get only register user with isRegister = user.phoneNumber == contact.phoneNumber
import Foundation
import Vapor
import Fluent
import FluentMongoDriver
public final class User: Model, Content, Hashable {
public static var schema = "users"
public init() {}
public init(id: ObjectId? = nil ,phoneNumber: String) {
self.id = id
self.phoneNumber = phoneNumber
self.firstName = nil
self.lastName = nil
}
@ID(custom: "id") public var id: ObjectId?
@Field(key: "phoneNumber") public var phoneNumber: String
@OptionalField(key: "firstName") public var firstName: String?
@OptionalField(key: "lastName") public var lastName: String?
@OptionalField(key: "email") public var email: String?
@Children(for: \.$owner) public var events: [Event]
@Children(for: \.$sender) public var senders: [Message]
@Children(for: \.$recipient) public var recipients: [Message]
@Children(for: \.$contact) public var contacts: [Contact]
@Siblings(through: UserConversation.self, from: \.$member, to: \.$conversation)
public var memberConversaions: [Conversation]
@Siblings(through: UserConversation.self, from: \.$admin, to: \.$conversation)
public var adminConversations: [Conversation]
@Timestamp(key: "createdAt", on: .create) public var createdAt: Date?
@Timestamp(key: "updatedAt", on: .update) public var updatedAt: Date?
@Timestamp(key: "deletedAt", on: .delete) public var deletedAt: Date?
public func hash(into hasher: inout Hasher) {
hasher.combine(id)
}
public static func == (lhs: User, rhs: User) -> Bool {
lhs.id == rhs.id
}
}
extension User {
public var amConversations: [Conversation] {
return self.adminConversations + self.memberConversaions
}
public var response: Response {
.init(self)
}
public struct Response: Content {
public init(_ user: User) {
self.id = user.id
self.firstName = user.firstName
self.lastName = user.lastName
self.email = user.email
self.phoneNumber = user.phoneNumber
self.createdAt = user.createdAt
self.updatedAt = user.updatedAt
self.deletedAt = user.deletedAt
}
public var id: ObjectId?
public var firstName, lastName, email: String?
public var phoneNumber: String
public var adminsConversations: [Conversation]?
public var membersConversaions: [Conversation]?
public var createdAt, updatedAt, deletedAt: Date?
}
}
import Vapor
import Fluent
import FluentMongoDriver
public final class Contact: Model, Content {
public static var schema = "contacts"
public init() {}
public init(id: ObjectId? = nil, phoneNumber: String, identifier: String, fullName: String? = nil, avatar: String? = nil, isRegister: Bool? = false, userId: User.IDValue) {
self.id = id
self.phoneNumber = phoneNumber
self.identifier = identifier
self.avatar = avatar
self.isRegister = isRegister
self.$contact.id = userId
}
// var uuid: String?
@ID(custom: "id") public var id: ObjectId?
@Field(key: "phoneNumber") public var phoneNumber: String
@Field(key: "identifier") public var identifier: String
@Field(key: "fullName") public var fullName: String?
@Field(key: "avatar") public var avatar: String?
@Field(key: "isRegister") public var isRegister: Bool?
@OptionalParent(key: "userId") public var contact: User?
@Timestamp(key: "createdAt", on: .create) public var createdAt: Date?
@Timestamp(key: "updatedAt", on: .update) public var updatedAt: Date?
@Timestamp(key: "deletedAt", on: .delete) public var deletedAt: Date?
}
extension Contact: Hashable {
public func hash(into hasher: inout Hasher) {
hasher.combine(phoneNumber)
}
public static func ==(lhs: Contact, rhs: Contact) -> Bool {
return lhs.phoneNumber == rhs.phoneNumber
}
}
public struct CreateContact: Content {
var identifier: String?
var phoneNumber: String
var fullName: String?
var avatar: String?
var isRegister: Bool?
var userId: String
}
extension CreateContact: Hashable {
public func hash(into hasher: inout Hasher) {
hasher.combine(phoneNumber)
}
public static func ==(lhs: CreateContact, rhs: CreateContact) -> Bool {
return lhs.phoneNumber == rhs.phoneNumber
}
}
// class ContactsController {
func create(_ req: Request) throws -> EventLoopFuture<[Contact]> {
if req.loggedIn == false { throw Abort(.unauthorized) }
let inputData = try req.content.decode([Contact].self)
return Contact.query(on: req.db)
.filter(\.$contact.$id == req.payload.userId).all().flatMapThrowing { contacts in
let setOriginal = Set(inputData)
let setServerContacts = Set(contacts)
let uniqServer = setOriginal.subtracting(setServerContacts)
let uniqOrg = setServerContacts.subtracting(setOriginal)
if uniqServer.isEmpty && uniqOrg.isEmpty {
throw Abort(.badRequest, reason: "No unique contacts.")
}
let newContacts = uniqServer.isEmpty ? uniqOrg : uniqServer
let results = newContacts.map { (contact: Contact) -> EventLoopFuture<Contact> in
let userO = User.query(on: req.db)
.filter(\.$phoneNumber == contact.contact!.phoneNumber)
.first()
guard let user = userO else {
return req.eventLoop.makeFailedFuture(Abort(.unauthorized))
}
let phoneNumber = user.flatMap { u -> String in u!.phoneNumber }
let contact = Contact(
phoneNumber: contact.phoneNumber,
identifier: contact.identifier,
fullName: contact.fullName,
avatar: contact.avatar!,
isRegister: phoneNumber == contact.phoneNumber ,
userId: contact.contact!.id!
)
contact.save(on: req.db).map {_ in contact }
}
return results.flatten(on: req.eventLoop).map { _ in results }
}
}
}
@tholo
Copy link

tholo commented Nov 12, 2020

Here is what I ended up with:

	func create(_ req: Request) throws -> EventLoopFuture<[Contact]> {
		if req.loggedIn == false { throw Abort(.unauthorized) }

		let inputData = try req.content.decode([Contact].self)

		return Contact.query(on: req.db).filter(\.$contact.$id == UUID()).all().flatMap { contacts in
			let setOriginal = Set(inputData)
			let setServerContacts = Set(contacts)
			let uniqServer = setOriginal.subtracting(setServerContacts)
			let uniqOrg = setServerContacts.subtracting(setOriginal)

			if uniqServer.isEmpty && uniqOrg.isEmpty {
				return req.eventLoop.makeFailedFuture(Abort(.badRequest, reason: "No unique contacts."))
			}

			let newContacts = uniqServer.isEmpty ? uniqOrg : uniqServer

			let results = newContacts.compactMap { (contact: Contact) -> EventLoopFuture<Contact> in
				let optionalNumber = User.query(on: req.db)
					.filter(\.$phoneNumber == contact.contact!.phoneNumber)
					.first()
					.flatMap { (user: User?) -> EventLoopFuture<String?> in
						guard let user = user else {
							return req.eventLoop.makeSucceededFuture(nil)
						}
						return req.eventLoop.makeSucceededFuture(user.phoneNumber)
					}

				return optionalNumber.flatMap { phoneNumber in
					guard let phoneNumber = phoneNumber else {
						return req.eventLoop.makeFailedFuture(Abort(.notFound))
					}

					let contact = Contact(
						phoneNumber: contact.phoneNumber,
						identifier: contact.identifier,
						fullName: contact.fullName,
						avatar: contact.avatar!,
						isRegister: phoneNumber == contact.phoneNumber,
						userId: contact.contact!.id!
					)

					return contact.save(on: req.db).map {_ in contact }
				}
			}

			return results.flatten(on: req.eventLoop)
		}
	}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment