Skip to content

Commit

Permalink
[feat] #152 SwiftSoupClient 로직 변경
Browse files Browse the repository at this point in the history
  • Loading branch information
ShapeKim98 committed Nov 17, 2024
1 parent 495989f commit e209baa
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,41 +12,14 @@ import SwiftSoup

extension SwiftSoupClient: DependencyKey {
public static let liveValue: Self = {
let provider = SwiftSoupProvider()

return Self(
parseOGTitleAndImage: { url, completion in
guard let html = try? String(contentsOf: url),
let document = try? SwiftSoup.parse(html) else {
await completion()
return (nil, nil)
}

let title = try? document.select("meta[property=og:title]").first()?.attr("content")
let imageURL = try? document.select("meta[property=og:image]").first()?.attr("content")

guard title != nil || imageURL != nil else {
var request = URLRequest(url: url)
request.setValue(
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36",
forHTTPHeaderField: "User-Agent"
)

guard let data = try? await URLSession.shared.data(for: request).0,
let html = String(data: data, encoding: .utf8),
let document = try? SwiftSoup.parse(html) else {
return (nil, nil)
}

let title = try? document.select("meta[property=og:title]").first()?.attr("content")
let imageURL = try? document.select("meta[property=og:image]").first()?.attr("content")

await completion()

return (title, imageURL)
}

await completion()

return (title, imageURL)
parseOGTitle: { url in
try await provider.parseOGTitle(url)
},
parseOGImageURL: { url in
try await provider.parseOGImageURL(url)
}
)
}()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@ import DependenciesMacros

@DependencyClient
public struct SwiftSoupClient {
public var parseOGTitleAndImage: @Sendable (
_ url: URL,
_ completion: @Sendable () async -> Void
) async -> (String?, String?) = { _, _ in (nil , nil) }
public var parseOGTitle: @Sendable (
_ url: URL
) async throws -> String? = { _ in nil }

public var parseOGImageURL: @Sendable (
_ url: URL
) async throws -> String? = { _ in nil }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//
// SwiftSoupProvider.swift
// CoreKit
//
// Created by 김도형 on 11/17/24.
//

import SwiftUI
import SwiftSoup

final class SwiftSoupProvider {
func parseOGTitle(_ url: URL) async throws -> String? {
return try await withCheckedThrowingContinuation { continuation in
do {
try parseOGMeta(url: url, type: "og:title", continuation: continuation)
} catch {
continuation.resume(throwing: error)
}
}
}

func parseOGImageURL(_ url: URL) async throws -> String? {
return try await withCheckedThrowingContinuation { continuation in
do {
try parseOGMeta(url: url, type: "og:image", continuation: continuation)
} catch {
continuation.resume(throwing: error)
}
}
}

func parseOGMeta(
url: URL,
type: String,
continuation: CheckedContinuation<String?, Error>
) throws {
let html = try String(contentsOf: url)
let document = try SwiftSoup.parse(html)

if let metaData = try document.select("meta[property=\(type)]").first()?.attr("content") {
continuation.resume(returning: metaData)
} else {
Task {
var request = URLRequest(url: url)
request.setValue(
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36",
forHTTPHeaderField: "User-Agent"
)

let (data, _) = try await URLSession.shared.data(for: request)
guard let html = String(data: data, encoding: .utf8) else {
continuation.resume(returning: nil)
return
}
let document = try SwiftSoup.parse(html)
let metaData = try document.select("meta[property=\(type)]").first()?.attr("content")

continuation.resume(returning: metaData)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -181,18 +181,17 @@ private extension ContentDetailFeature {
case .메타데이터_조회_수행(url: let url):
return .run { send in
/// - 링크에 대한 메타데이터의 제목 및 썸네일 항목 파싱
let (title, imageURL) = await swiftSoup.parseOGTitleAndImage(url) {
await send(.inner(.linkPreview), animation: .pokitDissolve)
}
await send(
async let title = swiftSoup.parseOGTitle(url)
async let imageURL = swiftSoup.parseOGImageURL(url)
try await send(
.inner(.메타데이터_조회_반영(title: title, imageURL: imageURL)),
animation: .pokitDissolve
)
}
case let .메타데이터_조회_반영(title: title, imageURL: imageURL):
state.linkTitle = title
state.linkImageURL = imageURL
return .none
return .send(.inner(.linkPreview), animation: .pokitDissolve)
case .URL_유효성_확인:
guard let urlString = state.domain.content?.data,
let url = URL(string: urlString) else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,10 +231,9 @@ private extension ContentSettingFeature {
return .none
case .메타데이터_조회_수행(url: let url):
return .run { send in
let (title, imageURL) = await swiftSoup.parseOGTitleAndImage(url) {
await send(.inner(.linkPreview), animation: .pokitDissolve)
}
await send(
async let title = swiftSoup.parseOGTitle(url)
async let imageURL = swiftSoup.parseOGImageURL(url)
try await send(
.inner(.메타데이텨_조회_반영(title: title, imageURL: imageURL)),
animation: .pokitDissolve
)
Expand All @@ -246,7 +245,7 @@ private extension ContentSettingFeature {
state.domain.title = title
}
state.domain.thumbNail = imageURL
return .none
return .send(.inner(.linkPreview), animation: .pokitDissolve)
case .URL_유효성_확인:
guard let url = URL(string: state.domain.data),
!state.domain.data.isEmpty else {
Expand Down

0 comments on commit e209baa

Please sign in to comment.