diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..433f32a4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +# .gitignore +Secrets.swift +build/ \ No newline at end of file diff --git a/AnimeGen.xcodeproj/project.pbxproj b/AnimeGen.xcodeproj/project.pbxproj index f4a4d123..0e7f7d9d 100644 --- a/AnimeGen.xcodeproj/project.pbxproj +++ b/AnimeGen.xcodeproj/project.pbxproj @@ -23,7 +23,6 @@ 1365E8072B920C110033C222 /* Printer@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1365E8062B920C110033C222 /* Printer@2x.png */; }; 1365E8092B920C1A0033C222 /* Generator@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1365E8082B920C1A0033C222 /* Generator@3x.png */; }; 1365E80B2B920C220033C222 /* Printer@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1365E80A2B920C220033C222 /* Printer@3x.png */; }; - 138661232B81216D0062AC91 /* Hmtai.swift in Sources */ = {isa = PBXBuildFile; fileRef = 138661222B81216D0062AC91 /* Hmtai.swift */; }; 138661252B8136DC0062AC91 /* nekosapi.swift in Sources */ = {isa = PBXBuildFile; fileRef = 138661242B8136DC0062AC91 /* nekosapi.swift */; }; 13877B192B82001800251A60 /* SettingsPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13877B182B82001800251A60 /* SettingsPage.swift */; }; 13877B1E2B82024A00251A60 /* AboutPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13877B1D2B82024A00251A60 /* AboutPage.swift */; }; @@ -35,7 +34,10 @@ 13910EC92B80D5C2009BF17E /* nekos-best.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13910EC82B80D5C2009BF17E /* nekos-best.swift */; }; 13910ECB2B80D5C8009BF17E /* waifu-pics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13910ECA2B80D5C8009BF17E /* waifu-pics.swift */; }; 13910ECF2B80D90D009BF17E /* SDWebImage in Frameworks */ = {isa = PBXBuildFile; productRef = 13910ECE2B80D90D009BF17E /* SDWebImage */; }; + 13A325922B94D8A100F1C357 /* Secrets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13A325912B94D8A100F1C357 /* Secrets.swift */; }; 13BE98C02B828B8000379AB7 /* nekosmoe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13BE98BF2B828B8000379AB7 /* nekosmoe.swift */; }; + 13C8011D2B94C5E900BFD198 /* HmtaiSender.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13C8011C2B94C5E900BFD198 /* HmtaiSender.swift */; }; + 13C8011F2B94CAD900BFD198 /* HmtaiReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13C8011E2B94CAD900BFD198 /* HmtaiReader.swift */; }; 13CC95082B8BA40100B5705E /* ApiPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13CC95072B8BA40100B5705E /* ApiPage.swift */; }; 13CC950A2B8BA43600B5705E /* API.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13CC95092B8BA43600B5705E /* API.xcassets */; }; /* End PBXBuildFile section */ @@ -59,7 +61,6 @@ 1365E8062B920C110033C222 /* Printer@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Printer@2x.png"; sourceTree = ""; }; 1365E8082B920C1A0033C222 /* Generator@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Generator@3x.png"; sourceTree = ""; }; 1365E80A2B920C220033C222 /* Printer@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Printer@3x.png"; sourceTree = ""; }; - 138661222B81216D0062AC91 /* Hmtai.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Hmtai.swift; sourceTree = ""; }; 138661242B8136DC0062AC91 /* nekosapi.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = nekosapi.swift; sourceTree = ""; }; 13877B182B82001800251A60 /* SettingsPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsPage.swift; sourceTree = ""; }; 13877B1D2B82024A00251A60 /* AboutPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutPage.swift; sourceTree = ""; }; @@ -70,7 +71,10 @@ 13910EC62B80D5B9009BF17E /* waifu-im.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "waifu-im.swift"; sourceTree = ""; }; 13910EC82B80D5C2009BF17E /* nekos-best.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "nekos-best.swift"; sourceTree = ""; }; 13910ECA2B80D5C8009BF17E /* waifu-pics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "waifu-pics.swift"; sourceTree = ""; }; + 13A325912B94D8A100F1C357 /* Secrets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Secrets.swift; sourceTree = ""; }; 13BE98BF2B828B8000379AB7 /* nekosmoe.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = nekosmoe.swift; sourceTree = ""; }; + 13C8011C2B94C5E900BFD198 /* HmtaiSender.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HmtaiSender.swift; sourceTree = ""; }; + 13C8011E2B94CAD900BFD198 /* HmtaiReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HmtaiReader.swift; sourceTree = ""; }; 13CC95072B8BA40100B5705E /* ApiPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApiPage.swift; sourceTree = ""; }; 13CC95092B8BA43600B5705E /* API.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = API.xcassets; sourceTree = ""; }; /* End PBXFileReference section */ @@ -116,10 +120,20 @@ 130A80582B78C02E0028985F /* Main.storyboard */, 130A805D2B78C0300028985F /* LaunchScreen.storyboard */, 130A80602B78C0300028985F /* Info.plist */, + 13A325912B94D8A100F1C357 /* Secrets.swift */, ); path = AnimeGen; sourceTree = ""; }; + 1317D4B22B9479CD00675214 /* Hmtai */ = { + isa = PBXGroup; + children = ( + 13C8011C2B94C5E900BFD198 /* HmtaiSender.swift */, + 13C8011E2B94CAD900BFD198 /* HmtaiReader.swift */, + ); + path = Hmtai; + sourceTree = ""; + }; 1365E7E72B8FA99C0033C222 /* Iconss */ = { isa = PBXGroup; children = ( @@ -177,11 +191,11 @@ 13910EC32B80D595009BF17E /* APIs */ = { isa = PBXGroup; children = ( + 1317D4B22B9479CD00675214 /* Hmtai */, 13910EC42B80D5A6009BF17E /* pic-re.swift */, 13910EC62B80D5B9009BF17E /* waifu-im.swift */, 13910ECA2B80D5C8009BF17E /* waifu-pics.swift */, 13910EC82B80D5C2009BF17E /* nekos-best.swift */, - 138661222B81216D0062AC91 /* Hmtai.swift */, 138661242B8136DC0062AC91 /* nekosapi.swift */, 13BE98BF2B828B8000379AB7 /* nekosmoe.swift */, ); @@ -284,6 +298,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 13A325922B94D8A100F1C357 /* Secrets.swift in Sources */, 13910EC72B80D5B9009BF17E /* waifu-im.swift in Sources */, 13877B192B82001800251A60 /* SettingsPage.swift in Sources */, 13BE98C02B828B8000379AB7 /* nekosmoe.swift in Sources */, @@ -291,11 +306,12 @@ 130A80532B78C02E0028985F /* AppDelegate.swift in Sources */, 130A80552B78C02E0028985F /* SceneDelegate.swift in Sources */, 13910ECB2B80D5C8009BF17E /* waifu-pics.swift in Sources */, - 138661232B81216D0062AC91 /* Hmtai.swift in Sources */, 13877B1E2B82024A00251A60 /* AboutPage.swift in Sources */, 13877B222B8233B800251A60 /* LicensePage.swift in Sources */, 13910EC52B80D5A6009BF17E /* pic-re.swift in Sources */, 1365E7E02B8FA2B70033C222 /* IconPage.swift in Sources */, + 13C8011D2B94C5E900BFD198 /* HmtaiSender.swift in Sources */, + 13C8011F2B94CAD900BFD198 /* HmtaiReader.swift in Sources */, 13910EC02B80D396009BF17E /* UIExtensions.swift in Sources */, 138661252B8136DC0062AC91 /* nekosapi.swift in Sources */, 13910EC92B80D5C2009BF17E /* nekos-best.swift in Sources */, diff --git a/AnimeGen.xcodeproj/project.xcworkspace/xcuserdata/Francesco.xcuserdatad/UserInterfaceState.xcuserstate b/AnimeGen.xcodeproj/project.xcworkspace/xcuserdata/Francesco.xcuserdatad/UserInterfaceState.xcuserstate index c31c25a0..bc13aae2 100644 Binary files a/AnimeGen.xcodeproj/project.xcworkspace/xcuserdata/Francesco.xcuserdatad/UserInterfaceState.xcuserstate and b/AnimeGen.xcodeproj/project.xcworkspace/xcuserdata/Francesco.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/AnimeGen/APIs/Hmtai.swift b/AnimeGen/APIs/Hmtai.swift deleted file mode 100644 index 505370e6..00000000 --- a/AnimeGen/APIs/Hmtai.swift +++ /dev/null @@ -1,91 +0,0 @@ -// -// Hmtai.swift -// AnimeGen -// -// Created by cranci on 17/02/24. -// - -import UIKit - -extension ViewController { - - func loadImagesFromHmtai() { - startLoadingIndicator() - - let categories3: [String] - let endpointPrefix: String - - if UserDefaults.standard.bool(forKey: "enableExplictiCont") { - categories3 = ["ass", "anal", "bdsm", "classic", "cum", "creampie", "manga", "femdom", "hentai", "incest", "masturbation", "public", "ero", "orgy", "elves", "yuri", "pantsu", "pussy", "glasses", "cuckold", "blowjob", "boobjob", "handjob", "footjob", "boobs", "thighs", "ahegao", "uniform", "gangbang", "tentacles", "gif", "nsfwNeko", "nsfwMobileWallpaper", "zettaiRyouiki"] - endpointPrefix = "https://hmtai.hatsunia.cfd/nsfw/" - } else { - categories3 = ["wave", "wink", "tea", "bonk", "punch", "poke", "bully", "pat", "kiss", "kick", "blush", "feed", "smug", "hug", "cuddle", "cry", "cringe", "slap", "five", "glomp", "happy", "hold", "nom", "smile", "throw", "lick", "bite", "dance", "boop", "sleep", "like", "kill", "tickle", "nosebleed", "threaten", "depression", "wolf_arts", "jahy_arts", "neko_arts", "coffee_arts", "wallpaper", "mobileWallpaper"] - endpointPrefix = "https://hmtai.hatsunia.cfd/sfw/" - } - - let randomCategory3 = categories3.randomElement() ?? "pat" - - let apiEndpoint = "\(endpointPrefix)\(randomCategory3)" - - guard let url = URL(string: apiEndpoint) else { - print("Invalid URL") - stopLoadingIndicator() - return - } - - let task = URLSession.shared.dataTask(with: url) { (data, response, error) in - DispatchQueue.main.async { - if let error = error { - print("Error loading image data: \(error.localizedDescription)") - self.stopLoadingIndicator() - return - } - - guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else { - print("Invalid HTTP response") - self.stopLoadingIndicator() - return - } - - if let jsonResponse = try? JSONSerialization.jsonObject(with: data ?? Data(), options: []) as? [String: Any], - let imageUrlString = jsonResponse["url"] as? String, - let imageUrl = URL(string: imageUrlString) { - print("Image URL: \(imageUrlString)") - - let imageDataTask = URLSession.shared.dataTask(with: imageUrl) { (imageData, _, imageError) in - DispatchQueue.main.async { - if let imageError = imageError { - print("Error loading image data: \(imageError.localizedDescription)") - self.stopLoadingIndicator() - return - } - - if let imageData = imageData, let newImage = UIImage(data: imageData) { - self.imageView.image = newImage - self.animateImageChange(with: newImage) - - let category3 = randomCategory3 - self.tagsLabel.isHidden = false - self.currentImageURL = imageUrlString - self.updateUIWithTags([category3]) - - self.stopLoadingIndicator() - } else { - print("Invalid image content or link issue.") - self.loadImagesFromHmtai() - } - } - } - - imageDataTask.resume() - } else { - print("Failed to parse JSON response or missing necessary data.") - self.stopLoadingIndicator() - } - } - } - - task.resume() - } - -} diff --git a/AnimeGen/APIs/Hmtai/HmtaiReader.swift b/AnimeGen/APIs/Hmtai/HmtaiReader.swift new file mode 100644 index 00000000..fb4d1aee --- /dev/null +++ b/AnimeGen/APIs/Hmtai/HmtaiReader.swift @@ -0,0 +1,67 @@ +// +// HmtaiReader.swift +// AnimeGen +// +// Created by cranci on 03/03/24. +// + +import UIKit + +extension ViewController { + + func fetchLastMessageFromDiscordAndLoadImage() { + + let discordChannelID = "1212099607031578674" + + let url = URL(string: "https://discord.com/api/v10/channels/\(discordChannelID)/messages")! + var request = URLRequest(url: url) + request.setValue(Secrets.apiToken, forHTTPHeaderField: "Authorization") + + let task = URLSession.shared.dataTask(with: request) { (data, response, error) in + if let data = data, let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [[String: Any]], let message = json.first { + if let imageUrl = self.extractImageUrl(from: message) { + self.loadImageFromDiscord(imageUrl: imageUrl) + } else { + print("Error extracting image URL from Discord message.") + print("Message JSON: \(self.convertDictionaryToJsonString(message) ?? "")") + } + } + } + + task.resume() + } + + func extractImageUrl(from message: [String: Any]) -> String? { + if let embeds = message["embeds"] as? [[String: Any]], let embed = embeds.first { + if let type = embed["type"] as? String, type == "image", let thumbnail = embed["thumbnail"] as? [String: Any] { + if let proxyUrl = thumbnail["proxy_url"] as? String { + return proxyUrl + } else if let url = thumbnail["url"] as? String { + return url + } + } + } + + return nil + } + + func loadImageFromDiscord(imageUrl: String) { + DispatchQueue.main.async { + self.imageView.loadImage(from: imageUrl) + + self.currentImageURL = imageUrl + + self.stopLoadingIndicator() + } + } + + func convertDictionaryToJsonString(_ dictionary: [String: Any]) -> String? { + do { + let jsonData = try JSONSerialization.data(withJSONObject: dictionary, options: .prettyPrinted) + return String(data: jsonData, encoding: .utf8) + } catch { + print("Error converting dictionary to JSON string: \(error)") + return nil + } + } +} diff --git a/AnimeGen/APIs/Hmtai/HmtaiSender.swift b/AnimeGen/APIs/Hmtai/HmtaiSender.swift new file mode 100644 index 00000000..cf404197 --- /dev/null +++ b/AnimeGen/APIs/Hmtai/HmtaiSender.swift @@ -0,0 +1,82 @@ +// +// HmtaiSender.swift +// AnimeGen +// +// Created by cranci on 03/03/24. +// + +import Foundation +import UIKit + +extension ViewController { + + @objc func fetchDataAndSendImageToDiscord() { + startLoadingIndicator() + + let categories3: [String] + let endpointPrefix: String + + if UserDefaults.standard.bool(forKey: "enableExplictiCont") { + categories3 = ["ass", "anal", "bdsm", "classic", "cum", "creampie", "manga", "femdom", "hentai", "incest", "masturbation", "public", "ero", "orgy", "elves", "yuri", "pantsu", "pussy", "glasses", "cuckold", "blowjob", "boobjob", "handjob", "footjob", "boobs", "thighs", "ahegao", "uniform", "gangbang", "tentacles", "gif", "nsfwNeko", "nsfwMobileWallpaper", "zettaiRyouiki"] + endpointPrefix = "https://hmtai.hatsunia.cfd/nsfw/" + } else { + categories3 = ["wave", "wink", "tea", "bonk", "punch", "poke", "bully", "pat", "kiss", "kick", "blush", "feed", "smug", "hug", "cuddle", "cry", "cringe", "slap", "five", "glomp", "happy", "hold", "nom", "smile", "throw", "lick", "bite", "dance", "boop", "sleep", "like", "kill", "tickle", "nosebleed", "threaten", "depression", "wolf_arts", "jahy_arts", "neko_arts", "coffee_arts", "wallpaper", "mobileWallpaper"] + endpointPrefix = "https://hmtai.hatsunia.cfd/sfw/" + } + + let randomCategory3 = categories3.randomElement() ?? "pat" + let apiEndpoint = "\(endpointPrefix)\(randomCategory3)" + + guard let url = URL(string: apiEndpoint) else { + print("Invalid URL") + self.stopLoadingIndicator() + return + } + + URLSession.shared.dataTask(with: url) { data, response, error in + guard let data = data, error == nil else { + print("Error fetching data: \(error?.localizedDescription ?? "Unknown error")") + return + } + + do { + let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] + + if let imageUrlString = json?["url"] as? String { + DispatchQueue.main.async { [weak self] in + self?.sendImageToDiscord(imageUrlString) + + let category3 = randomCategory3 + self?.tagsLabel.isHidden = false + self?.updateUIWithTags([category3]) + } + } else { + print("Error: Could not find 'url' field in the API response.") + } + } catch { + print("Error parsing JSON: \(error.localizedDescription)") + } + }.resume() + } + + private func sendImageToDiscord(_ imageUrlString: String) { + let discordWebhookURL = URL(string: "https://discord.com/api/webhooks/1213771285507735592/flCaAxQ8NuhnJML3P_YYFIOvSQxhmT8552nm4lQE2LgDWOzZvMGNaVsf7BJU4yqdQ_ql")! + + var request = URLRequest(url: discordWebhookURL) + request.httpMethod = "POST" + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + + let payload: [String: Any] = ["content": imageUrlString] + let jsonData = try? JSONSerialization.data(withJSONObject: payload) + + request.httpBody = jsonData + + URLSession.shared.dataTask(with: request) { [weak self] data, response, error in + if let error = error { + print("Error sending image URL to Discord: \(error.localizedDescription)") + } else { + self?.fetchLastMessageFromDiscordAndLoadImage() + } + }.resume() + } +} diff --git a/AnimeGen/Extensions/ImageExtensions.swift b/AnimeGen/Extensions/ImageExtensions.swift index af652b26..a3a6a09a 100644 --- a/AnimeGen/Extensions/ImageExtensions.swift +++ b/AnimeGen/Extensions/ImageExtensions.swift @@ -25,6 +25,12 @@ extension UIImage { var imageData: Data? { return self.sd_imageData() } - } +extension UIImageView { + func loadImage(from url: String) { + if let imageUrl = URL(string: url) { + self.sd_setImage(with: imageUrl, completed: nil) + } + } +} diff --git a/AnimeGen/ViewController.swift b/AnimeGen/ViewController.swift index 6c33932a..52c2cb67 100644 --- a/AnimeGen/ViewController.swift +++ b/AnimeGen/ViewController.swift @@ -108,7 +108,7 @@ class ViewController: UIViewController { settingsButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 10), ]) - let webButton = UIButton(type: .system) + webButton = UIButton(type: .system) let webIcon = UIImage(systemName: "safari.fill")? .withConfiguration(UIImage.SymbolConfiguration(pointSize: 25, weight: .bold)) webButton.setImage(webIcon, for: .normal) @@ -230,7 +230,7 @@ class ViewController: UIViewController { case "waifu.pics": loadImageFromWaifuPics() case "Hmtai": - loadImagesFromHmtai() + fetchDataAndSendImageToDiscord() case "Nekos api": loadImageAndTagsFromNekosapi() case "nekos.moe": @@ -275,7 +275,7 @@ class ViewController: UIViewController { loadImageFromWaifuPics() case "Hmtai": lastImage = imageView.image - loadImagesFromHmtai() + fetchDataAndSendImageToDiscord() case "Nekos api": lastImage = imageView.image loadImageAndTagsFromNekosapi() @@ -360,8 +360,7 @@ class ViewController: UIViewController { if let error = error { print("Error saving image: \(error.localizedDescription)") } else { - print("Image saved successfully!") - animateFeedback() + print("Image saved successfully") } } @@ -370,5 +369,4 @@ class ViewController: UIViewController { UIApplication.shared.open(url, options: [:], completionHandler: nil) } } - }