|
|
@ -133,8 +133,8 @@ public class OWSLinkPreview: MTLModel {
|
|
|
|
Logger.error("Preview for message without body.")
|
|
|
|
Logger.error("Preview for message without body.")
|
|
|
|
throw LinkPreviewError.invalidInput
|
|
|
|
throw LinkPreviewError.invalidInput
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let bodyComponents = body.components(separatedBy: .whitespacesAndNewlines)
|
|
|
|
let previewUrls = allPreviewUrls(forMessageBodyText: body)
|
|
|
|
guard bodyComponents.contains(urlString) else {
|
|
|
|
guard previewUrls.contains(urlString) else {
|
|
|
|
Logger.error("URL not present in body.")
|
|
|
|
Logger.error("URL not present in body.")
|
|
|
|
throw LinkPreviewError.invalidInput
|
|
|
|
throw LinkPreviewError.invalidInput
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -395,15 +395,6 @@ public class OWSLinkPreview: MTLModel {
|
|
|
|
public class func previewUrl(forMessageBodyText body: String?) -> String? {
|
|
|
|
public class func previewUrl(forMessageBodyText body: String?) -> String? {
|
|
|
|
AssertIsOnMainThread()
|
|
|
|
AssertIsOnMainThread()
|
|
|
|
|
|
|
|
|
|
|
|
guard OWSLinkPreview.featureEnabled else {
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
guard SSKPreferences.areLinkPreviewsEnabled() else {
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
guard let body = body else {
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if let cachedUrl = previewUrlCache.object(forKey: body as AnyObject) as? String {
|
|
|
|
if let cachedUrl = previewUrlCache.object(forKey: body as AnyObject) as? String {
|
|
|
|
Logger.verbose("URL parsing cache hit.")
|
|
|
|
Logger.verbose("URL parsing cache hit.")
|
|
|
|
guard cachedUrl.count > 0 else {
|
|
|
|
guard cachedUrl.count > 0 else {
|
|
|
@ -411,17 +402,51 @@ public class OWSLinkPreview: MTLModel {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return cachedUrl
|
|
|
|
return cachedUrl
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let components = body.components(separatedBy: .whitespacesAndNewlines)
|
|
|
|
let previewUrls = allPreviewUrls(forMessageBodyText: body)
|
|
|
|
for component in components {
|
|
|
|
guard let previewUrl = previewUrls.first else {
|
|
|
|
let urlString = stripPossibleLinkUrl(component)
|
|
|
|
// Use empty string to indicate "no preview URL" in the cache.
|
|
|
|
|
|
|
|
previewUrlCache.setObject("" as AnyObject, forKey: body as AnyObject)
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
previewUrlCache.setObject(previewUrl as AnyObject, forKey: body as AnyObject)
|
|
|
|
|
|
|
|
return previewUrl
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class func allPreviewUrls(forMessageBodyText body: String?) -> [String] {
|
|
|
|
|
|
|
|
AssertIsOnMainThread()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
guard OWSLinkPreview.featureEnabled else {
|
|
|
|
|
|
|
|
return []
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
guard SSKPreferences.areLinkPreviewsEnabled() else {
|
|
|
|
|
|
|
|
return []
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
guard let body = body else {
|
|
|
|
|
|
|
|
return []
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let detector: NSDataDetector
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
|
|
|
detector = try NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue)
|
|
|
|
|
|
|
|
} catch {
|
|
|
|
|
|
|
|
owsFailDebug("Could not create NSDataDetector: \(error).")
|
|
|
|
|
|
|
|
return []
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var previewUrls = [String]()
|
|
|
|
|
|
|
|
let matches = detector.matches(in: body, options: [], range: NSRange(location: 0, length: body.count))
|
|
|
|
|
|
|
|
for match in matches {
|
|
|
|
|
|
|
|
guard let matchURL = match.url else {
|
|
|
|
|
|
|
|
owsFailDebug("Match missing url")
|
|
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
let urlString = matchURL.absoluteString
|
|
|
|
if isValidLinkUrl(urlString) {
|
|
|
|
if isValidLinkUrl(urlString) {
|
|
|
|
previewUrlCache.setObject(urlString as AnyObject, forKey: body as AnyObject)
|
|
|
|
previewUrls.append(urlString)
|
|
|
|
return urlString
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Use empty string to indicate "no preview URL" in the cache.
|
|
|
|
return previewUrls
|
|
|
|
previewUrlCache.setObject("" as AnyObject, forKey: body as AnyObject)
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// MARK: - Preview Construction
|
|
|
|
// MARK: - Preview Construction
|
|
|
|