Skip to content

Commit

Permalink
nekos.moe support
Browse files Browse the repository at this point in the history
  • Loading branch information
cranci1 committed Feb 19, 2024
1 parent 545fa04 commit 165d652
Show file tree
Hide file tree
Showing 12 changed files with 215 additions and 4 deletions.
4 changes: 4 additions & 0 deletions AnimeGen.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
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 */; };
13BE98C02B828B8000379AB7 /* nekosmoe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13BE98BF2B828B8000379AB7 /* nekosmoe.swift */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
Expand All @@ -47,6 +48,7 @@
13910EC62B80D5B9009BF17E /* waifu-im.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "waifu-im.swift"; sourceTree = "<group>"; };
13910EC82B80D5C2009BF17E /* nekos-best.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "nekos-best.swift"; sourceTree = "<group>"; };
13910ECA2B80D5C8009BF17E /* waifu-pics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "waifu-pics.swift"; sourceTree = "<group>"; };
13BE98BF2B828B8000379AB7 /* nekosmoe.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = nekosmoe.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -113,6 +115,7 @@
13910EC82B80D5C2009BF17E /* nekos-best.swift */,
138661222B81216D0062AC91 /* Hmtai.swift */,
138661242B8136DC0062AC91 /* nekosapi.swift */,
13BE98BF2B828B8000379AB7 /* nekosmoe.swift */,
);
path = APIs;
sourceTree = "<group>";
Expand Down Expand Up @@ -205,6 +208,7 @@
files = (
13910EC72B80D5B9009BF17E /* waifu-im.swift in Sources */,
13877B192B82001800251A60 /* SettingsPage.swift in Sources */,
13BE98C02B828B8000379AB7 /* nekosmoe.swift in Sources */,
130A80572B78C02E0028985F /* ViewController.swift in Sources */,
130A80532B78C02E0028985F /* AppDelegate.swift in Sources */,
130A80552B78C02E0028985F /* SceneDelegate.swift in Sources */,
Expand Down
Binary file not shown.
3 changes: 2 additions & 1 deletion AnimeGen/APIs/Hmtai.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ extension ViewController {
let endpointPrefix: String

if UserDefaults.standard.bool(forKey: "enableExplictiCont") {
// If explicit content is enabled, include NSFW categories
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 {
Expand Down Expand Up @@ -69,6 +68,8 @@ extension ViewController {

let category3 = randomCategory3

self.tagsLabel.isHidden = false

self.currentImageURL = imageUrlString

self.updateUIWithTags([category3])
Expand Down
1 change: 1 addition & 0 deletions AnimeGen/APIs/nekos-best.swift
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ extension ViewController {

if let data = try? Data(contentsOf: imageUrl), let newImage = UIImage(data: data) {
self.imageView.image = newImage
self.tagsLabel.isHidden = false
self.animateImageChange(with: newImage)
self.updateUIWithTags([], author: author, category: category)
self.stopLoadingIndicator()
Expand Down
4 changes: 3 additions & 1 deletion AnimeGen/APIs/nekosapi.swift
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ extension ViewController {
if let data = try? Data(contentsOf: imageUrl), let newImage = UIImage(data: data) {
self.imageView.image = newImage
self.animateImageChange(with: newImage)


self.tagsLabel.isHidden = false

self.updateUIWithTags(tags)

self.stopLoadingIndicator()
Expand Down
163 changes: 163 additions & 0 deletions AnimeGen/APIs/nekosmoe.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
//
// nekosmoe.swift
// AnimeGen
//
// Created by cranci on 18/02/24.
//

import UIKit

extension ViewController {

func loadImageAndTagsFromNekosMoe() {
startLoadingIndicator()

let isNSFW = UserDefaults.standard.bool(forKey: "enableExplictiCont")
let moetags = UserDefaults.standard.bool(forKey: "enableMoeTags")

let apiEndpoint = "https://nekos.moe/api/v1/random/image"

var components = URLComponents(string: apiEndpoint)
components?.queryItems = [
URLQueryItem(name: "nsfw", value: isNSFW.description.lowercased())
]

guard let url = components?.url else {
print("Invalid URL")
stopLoadingIndicator()
return
}

var request = URLRequest(url: url)
request.httpMethod = "GET"

let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
DispatchQueue.main.async {
if let error = error {
print("Error: \(error)")
self.stopLoadingIndicator()
return
}

guard let httpResponse = response as? HTTPURLResponse else {
print("Invalid HTTP response")
self.stopLoadingIndicator()
return
}

guard httpResponse.statusCode == 200 else {
print("Invalid status code: \(httpResponse.statusCode)")
self.stopLoadingIndicator()
return
}

do {
if let jsonData = data,
let jsonResponse = try? JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any],
let images = jsonResponse["images"] as? [[String: Any]],
let firstImage = images.first {

let imageId = firstImage["id"] as? String

if moetags {
if let tagsArray = firstImage["tags"] as? [String] {
// Print tags for debugging
print("Tags: \(tagsArray)")

// Update UI with tags
self.updateUIWithTags(tagsArray)

var newComponents = URLComponents(string: "https://nekos.moe/thumbnail/\(imageId ?? "")")
newComponents?.queryItems = [
URLQueryItem(name: "tags", value: tagsArray.joined(separator: ","))
// Add more query parameters as needed
]

guard let newUrl = newComponents?.url else {
print("Invalid URL with tags")
self.stopLoadingIndicator()
return
}

let imageRequest = URLRequest(url: newUrl)
let imageTask = URLSession.shared.dataTask(with: imageRequest) { (imageData, _, imageError) in
DispatchQueue.main.async {
if let imageError = imageError {
print("Image loading error: \(imageError)")
self.stopLoadingIndicator()
return
}

if let imageData = imageData, let newImage = UIImage(data: imageData) {
self.imageView.image = newImage
self.animateImageChange(with: newImage)

// Continue with the rest of your code here
// Add any additional logic or UI updates you need

// Temporarily hide the tag label when using nekos.moe API
self.tagsLabel.isHidden = true

self.stopLoadingIndicator()
} else {
print("Failed to load image data with tags.")
self.stopLoadingIndicator()
}
}
}

imageTask.resume()
} else {
print("Tags data not available.")
self.stopLoadingIndicator()
}
} else {
// Load the image without tags
var newComponents = URLComponents(string: "https://nekos.moe/thumbnail/\(imageId ?? "")")

guard let newUrl = newComponents?.url else {
print("Invalid URL without tags")
self.stopLoadingIndicator()
return
}

let imageRequest = URLRequest(url: newUrl)
let imageTask = URLSession.shared.dataTask(with: imageRequest) { (imageData, _, imageError) in
DispatchQueue.main.async {
if let imageError = imageError {
print("Image loading error: \(imageError)")
self.stopLoadingIndicator()
return
}

if let imageData = imageData, let newImage = UIImage(data: imageData) {
self.imageView.image = newImage
self.animateImageChange(with: newImage)

// Continue with the rest of your code here
// Add any additional logic or UI updates you need

// Temporarily hide the tag label when using nekos.moe API
self.tagsLabel.isHidden = true

self.stopLoadingIndicator()
} else {
print("Failed to load image data without tags.")
self.stopLoadingIndicator()
}
}
}

imageTask.resume()
}
} else {
print("Failed to parse JSON response or missing necessary data.")
self.stopLoadingIndicator()
}
}
}
}

task.resume()
}
}
1 change: 1 addition & 0 deletions AnimeGen/APIs/pic-re.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ extension ViewController {
}

DispatchQueue.main.async {
self.tagsLabel.isHidden = false
self.imageView.image = newImage
self.animateImageChange(with: newImage)
self.stopLoadingIndicator()
Expand Down
3 changes: 2 additions & 1 deletion AnimeGen/APIs/waifu-im.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ extension ViewController {
var components = URLComponents(string: apiEndpoint)
components?.queryItems = [
URLQueryItem(name: "is_nsfw", value: isNSFW ? "true" : "false")
// Add more query parameters as needed
]

guard let url = components?.url else {
Expand Down Expand Up @@ -67,6 +66,8 @@ extension ViewController {
if let data = try? Data(contentsOf: imageUrl), let newImage = UIImage(data: data) {
self.imageView.image = newImage
self.animateImageChange(with: newImage)

self.tagsLabel.isHidden = false

self.updateUIWithTags(tags)

Expand Down
2 changes: 2 additions & 0 deletions AnimeGen/APIs/waifu-pics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ extension ViewController {

self.currentImageURL = imageUrlString

self.tagsLabel.isHidden = false

self.updateUIWithTags([randomCategory])

self.stopLoadingIndicator()
Expand Down
8 changes: 8 additions & 0 deletions AnimeGen/Settings/SettingsPage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ struct SettingsPage: View {
// Features
@State private var animations = UserDefaults.standard.bool(forKey: "enableAnimations")
@State private var tags = UserDefaults.standard.bool(forKey: "enableTags")
@State private var moetags = UserDefaults.standard.bool(forKey: "enableMoeTags")

// Content
@State private var suggestiveCont = UserDefaults.standard.bool(forKey: "enablesuggestiveCont")
Expand All @@ -37,6 +38,13 @@ struct SettingsPage: View {
UserDefaults.standard.set(newValue, forKey: "enableTags")
}
))
Toggle("Display nekos.moe Tags", isOn: Binding(
get: { self.moetags },
set: { newValue in
self.moetags = newValue
UserDefaults.standard.set(newValue, forKey: "enableMoeTags")
}
))
}

Section(header: Text("Content"), footer: Text("Caution: This content is on the borderline of explicit material and includes adult content. Viewer discretion is advised.")) {
Expand Down
9 changes: 8 additions & 1 deletion AnimeGen/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ class ViewController: UIViewController {

var enableAnimations = UserDefaults.standard.bool(forKey: "enableAnimations")

var moetags = UserDefaults.standard.bool(forKey: "enableMoeTags")

override func viewDidLoad() {
super.viewDidLoad()

Expand Down Expand Up @@ -227,6 +229,8 @@ class ViewController: UIViewController {
loadImagesFromHmtai()
case "Nekos api":
loadImageAndTagsFromNekosapi()
case "nekos.moe":
loadImageAndTagsFromNekosMoe()
default:
break
}
Expand Down Expand Up @@ -271,6 +275,9 @@ class ViewController: UIViewController {
case "Nekos api":
lastImage = imageView.image
loadImageAndTagsFromNekosapi()
case "nekos.moe":
lastImage = imageView.image
loadImageAndTagsFromNekosMoe()
default:
break
}
Expand All @@ -280,7 +287,7 @@ class ViewController: UIViewController {
@objc func apiButtonTapped() {
let alertController = UIAlertController(title: "Select API", message: nil, preferredStyle: .actionSheet)

let apiOptions = ["Nekos api", "Hmtai", "waifu.pics", "nekos.best", "waifu.im", "pic.re"]
let apiOptions = ["nekos.moe", "Nekos api", "Hmtai", "waifu.pics", "nekos.best", "waifu.im", "pic.re"]
for option in apiOptions {
let action = UIAlertAction(title: option, style: .default) { _ in
self.apiButton.setTitle(option, for: .normal)
Expand Down
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,27 @@ Its Made to support any iOS/iPadOS device running iOS 13+
- [waifu.pics api](https://waifu.pics/docs) SFW/NSFW
- [Hmtai api](https://hmtai.hatsunia.cfd/endpoints) SFW/NSFW
- [Nekos api](https://nekosapi.com/docs) SFW/NSFW
- [Nekos.moe](https://docs.nekos.moe) SFW/NSFW

<table>
<tr>
<th>Working APIs</th>
<th>Type</th>
</tr>
<tr><td>
| APIs | Type | Working |
| ------------------- | ----- | :--------: |
| Pic.re | SFW | :white_check_mark: |
| Waifu.im | SFW/NSFW | :white_check_mark: |
| Nekos.best | SFW | :white_check_mark: |
| Waifu.pics | SFW/NSFW | :white_check_mark: |
| Hmtai | SFW/NSFW | :white_check_mark: |
| Nekos api | SFW/NSFW | :white_check_mark: |
| Nekos.mod | SFW/NSFW | :white_check_mark: |

</table>


## Third Party Softwares

Expand Down

0 comments on commit 165d652

Please sign in to comment.