more regex to avoid mapping errors, hopefully

This commit is contained in:
686udjie 2025-12-06 00:29:45 +02:00
parent 3c80c65ca6
commit 9b85eea76c

View file

@ -1275,10 +1275,27 @@ struct MediaInfoView: View {
private func cleanTitle(_ title: String?) -> String { private func cleanTitle(_ title: String?) -> String {
guard let title = title else { return "Unknown" } guard let title = title else { return "Unknown" }
let cleaned = title.replacingOccurrences( var cleaned = title
of: "\\s*\\([^\\)]*\\)",
cleaned = cleaned.replacingOccurrences(
of: "\\s*[\\[\\(][^\\]\\)]*[\\]\\)]",
with: "", with: "",
options: .regularExpression options: .regularExpression
)
cleaned = cleaned.replacingOccurrences(
of: "\\s*(?i)(season|s)\\s*\\d+",
with: "",
options: .regularExpression
)
cleaned = cleaned.replacingOccurrences(
of: "\\s*(?i)(dub|sub|eng|jpn|raw)\\s*$",
with: "",
options: .regularExpression
)
cleaned = cleaned.replacingOccurrences(
of: "\\s+",
with: " ",
options: .regularExpression
).trimmingCharacters(in: .whitespaces) ).trimmingCharacters(in: .whitespaces)
return cleaned.isEmpty ? "Unknown" : cleaned return cleaned.isEmpty ? "Unknown" : cleaned
@ -1609,7 +1626,7 @@ struct MediaInfoView: View {
func fetchMetadataIDIfNeeded() { func fetchMetadataIDIfNeeded() {
let order = metadataProvidersOrder let order = metadataProvidersOrder
let cleanedTitle = cleanTitle(title) let titlesToTry = [cleanTitle(title), title] // Try cleaned first, then original
itemID = nil itemID = nil
tmdbID = nil tmdbID = nil
@ -1643,25 +1660,40 @@ struct MediaInfoView: View {
} }
} }
fetchItemID(byTitle: cleanedTitle) { result in func tryAniListTitles(index: Int) {
DispatchQueue.main.async { if index >= titlesToTry.count {
aniListCompleted = true // All failed
DispatchQueue.main.async {
aniListCompleted = true
Logger.shared.log("Failed to fetch AniList ID for all title variations", type: "Debug")
checkCompletion()
}
return
}
let currentTitle = titlesToTry[index]
fetchItemID(byTitle: currentTitle) { result in
switch result { switch result {
case .success(let id): case .success(let id):
self.itemID = id DispatchQueue.main.async {
aniListSuccess = true self.itemID = id
Logger.shared.log("Successfully fetched AniList ID: \(id)", type: "Debug") aniListSuccess = true
self.fetchMalIDFromAniList(anilistID: id) { fetchedMalID in Logger.shared.log("Successfully fetched AniList ID: \(id) using title: \(currentTitle)", type: "Debug")
self.matchedMalID = fetchedMalID self.fetchMalIDFromAniList(anilistID: id) { fetchedMalID in
self.matchedMalID = fetchedMalID
}
aniListCompleted = true
checkCompletion()
} }
case .failure(let error): case .failure:
Logger.shared.log("Failed to fetch AniList ID: \(error)", type: "Debug") Logger.shared.log("Failed to fetch AniList ID with title: \(currentTitle), trying next variation", type: "Debug")
tryAniListTitles(index: index + 1)
} }
checkCompletion()
} }
} }
tmdbFetcher.fetchBestMatchID(for: cleanedTitle) { id, type in tryAniListTitles(index: 0)
tmdbFetcher.fetchBestMatchID(for: titlesToTry.first ?? title) { id, type in
DispatchQueue.main.async { DispatchQueue.main.async {
tmdbCompleted = true tmdbCompleted = true
if let id = id, let type = type { if let id = id, let type = type {
@ -1678,11 +1710,19 @@ struct MediaInfoView: View {
} }
private func fetchItemID(byTitle title: String, completion: @escaping (Result<Int, Error>) -> Void) { private func fetchItemID(byTitle title: String, completion: @escaping (Result<Int, Error>) -> Void) {
Logger.shared.log("Searching AniList for title: \(title)", type: "Debug")
let query = """ let query = """
query { query {
Media(search: "\(title)", type: ANIME) { Page(page: 1, perPage: 1) {
id media(search: "\(title)", type: ANIME) {
id
idMal
title {
romaji
english
}
} }
}
} }
""" """
@ -1694,9 +1734,7 @@ struct MediaInfoView: View {
var request = URLRequest(url: url) var request = URLRequest(url: url)
request.httpMethod = "POST" request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: ["query": query])
let parameters: [String: Any] = ["query": query]
request.httpBody = try? JSONSerialization.data(withJSONObject: parameters)
URLSession.custom.dataTask(with: request) { data, _, error in URLSession.custom.dataTask(with: request) { data, _, error in
if let error = error { if let error = error {
@ -1711,12 +1749,16 @@ struct MediaInfoView: View {
do { do {
if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any], if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
let data = json["data"] as? [String: Any], let dataDict = json["data"] as? [String: Any],
let media = data["Media"] as? [String: Any], let page = dataDict["Page"] as? [String: Any],
let id = media["id"] as? Int { let mediaList = page["media"] as? [[String: Any]],
let firstMedia = mediaList.first,
let id = firstMedia["id"] as? Int {
Logger.shared.log("AniList match found: ID \(id)", type: "Debug")
completion(.success(id)) completion(.success(id))
} else { } else {
let error = NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey: "Invalid response"]) Logger.shared.log("No AniList matches found for title: \(title)", type: "Debug")
let error = NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey: "Invalid response or no matches"])
completion(.failure(error)) completion(.failure(error))
} }
} catch { } catch {