Skip to content

Instantly share code, notes, and snippets.

@Grohden
Last active March 19, 2020 16:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Grohden/f2fb1d789be87cc2589950c2928dbb96 to your computer and use it in GitHub Desktop.
Save Grohden/f2fb1d789be87cc2589950c2928dbb96 to your computer and use it in GitHub Desktop.
NHentai rest api (kinda not documented) consumed and mapped by graphql
directive @client on FIELD
type GalleryItemImage {
t: String!,
w: Int!,
h: Int
}
type GalleryItemTag {
count: Int!
id: ID
name: String!
type: String!
url: String!
}
type GalleryItemImages {
cover: GalleryItemImage!
thumbnail: GalleryItemImage!
pages: [GalleryItemImage!]!
}
type GalleryItemTitle {
english: String
japanese: String
pretty: String!
}
"""
This is the principal item returned by the nHentai api
when you open a item, this is returned and used
to render the contents of the hentai
"""
type GalleryItem {
id: String!
media_id: String!
num_favorites: Int!
num_pages: Int!
scanlator: String!
images: GalleryItemImages!
tags: [GalleryItemTag!]!
title: GalleryItemTitle!
upload_date: Int
}
"""
This item represents a nHentai page, containing
the number of pages of a determinated subject (tag, artist, etc.)
the number of results per page and the result itself
"""
type GalleryPage {
num_pages: Int!
per_page: Int!
result: [GalleryItem]!
}
enum SortType {
popular
date
}
type Query {
all(sort: SortType, page: Int): GalleryPage!
search(query: String!, sort: SortType, page: Int): GalleryPage
byTagId(tagId: Int!, sort: SortType, page: Int): GalleryPage
related(bookId: String!): GalleryItem
details(bookId: String!): GalleryItem
}
import Axios from 'axios'
const API = 'https://nhentai.net/api'
type TSort = 'popular' | 'date'
type TBaseArg<T = {}> = {
sort?: TSort
page: number
} & T
const toQueryParams = <T extends { [key: string]: any }>(arg: T, defaults: T) =>
Object
.entries(arg)
.map(([key, value]) => `${key}=${value || defaults[key]}`)
.join('&')
export default {
Query: {
all: async (_: unknown, args: TBaseArg) => {
const queryParams = toQueryParams(args, {
sort: "date",
page: 1
})
const response = await Axios.get(`${API}/galleries/all?page=${queryParams}`)
return response.data
},
search: async(_: unknown, args: TBaseArg<{ query: string }>) => {
const queryParams = toQueryParams(args, {
sort: "date",
page: 1,
query: args.query
})
const response = await Axios.get(`${API}/galleries/search?${queryParams}`)
return response.data
},
byTagId: async(_: unknown, args: TBaseArg<{ tagId: string }>) => {
const { tagId, ...rest } = args
const queryParams = toQueryParams({ ...rest, tag_id: tagId }, {
tag_id: tagId,
page: 1,
sort: "date"
})
const response = await Axios.get(`${API}/galleries/tagged?${queryParams}`)
return response.data
},
related: async(_: unknown, args: { bookId: string }) => {
const { bookId } = args
const response = await Axios.get(`${API}/gallery/${bookId}/related`)
return response.data
},
details: async(_: unknown, args: { bookId: string }) => {
const { bookId } = args
const response = await Axios.get(`${API}/gallery/${bookId}`)
return response.data
}
}
}
import 'package:flambda/flambda.dart';
// ignore: avoid_classes_with_only_static_members
class NHentaiUrls {
static String tagPage(String tag, int pageNumber) {
return 'https://nhentai.net/tag/$tag/popular?page=$pageNumber';
}
static String home({int page = 1}) {
assert(page > 0);
return 'https://nhentai.net/?page=$page';
}
static String manga(int id) {
return 'https://nhentai.net/g/$id';
}
static Uri mangaLink(String urlPart) {
return Uri.parse('https://nhentai.net$urlPart');
}
static String search(String term, {int page = 1}) {
assert(page > 0);
return 'https://nhentai.net/search/?q=$term&page=$page';
}
static String galleryImage(String mediaId, int number, String type) {
final ext = _mapImageType(type);
return 'https://i.nhentai.net/galleries/$mediaId/$number.$ext';
}
static String thumbImage(String mediaId, int number, String type) {
final ext = _mapImageType(type);
return 'https://t.nhentai.net/galleries/$mediaId/${number}t.$ext';
}
static String coverThumb(String mediaId, String type) {
final ext = _mapImageType(type);
return 'https://t.nhentai.net/galleries/$mediaId/thumb.$ext';
}
static String cover(String mediaId, String type) {
final ext = _mapImageType(type);
return 'https://t.nhentai.net/galleries/$mediaId/cover.$ext';
}
static final _mapImageType = cond<String, String>([
Case(eq('j'), always('jpg')),
Case(eq('p'), always('png')),
Case.otherwise((type) => throw ArgumentError('Unknown type $type')),
]);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment