-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathSearchResults.ts
123 lines (110 loc) · 3.26 KB
/
SearchResults.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/**
* @packageDocumentation
* @module Structures
*/
import * as Utils from '../Utils'
import type Booru from '../boorus/Booru'
import type Post from '../structures/Post'
import type SearchParameters from './SearchParameters'
/**
* Represents a page of search results, works like an array of {@link Post}
* <p> Usable like an array and allows to easily get the next page
*
* @example
* ```
* const Booru = require('booru')
* // Safebooru
* const sb = new Booru('sb')
*
* const imgs = await sb.search('cat')
*
* // Log the images from the first page, then from the second
* imgs.forEach(i => console.log(i.postView))
* const imgs2 = await imgs.nextPage()
* imgs2.forEach(i => console.log(i.postView))
* ```
*/
export default class SearchResults extends Array<Post> {
/** The booru used for this search */
public booru: Booru
/** The page of this search */
public page: number
/** The tags used for this search */
public readonly tags: string[]
/** The options used for this search */
public readonly options: SearchParameters
/** The posts from this search result */
public readonly posts: Post[]
/** @private */
constructor(
posts: Post[],
tags: string[],
options: SearchParameters,
booru: Booru,
) {
super(posts.length)
for (let i = 0; i < posts.length; i++) {
this[i] = posts[i]
}
this.posts = posts
this.tags = tags
this.options = options
this.booru = booru
this.page = options ? (options.page ?? 0) : 0
}
/**
* Get the first post in this result set
* @return {Post}
*/
get first(): Post {
return this[0]
}
/**
* Get the last post in this result set
* @return {Post}
*/
get last(): Post {
return this[this.length - 1]
}
/**
* Get the next page
* <p>Works like <code>sb.search('cat', {page: 1}); sb.search('cat', {page: 2})</code>
* @return {Promise<SearchResults>}
*/
public nextPage(): Promise<SearchResults> {
const opts: SearchParameters = this.options
opts.page = this.page + 1
return this.booru.search(this.tags, opts)
}
/**
* Create a new SearchResults with just images with the matching tags
*
* @param {String[]|String} tags The tags (or tag) to search for
* @param {Object} options The extra options for the search
* @param {Boolean} [options.invert=false] If the results should be inverted and
* return images *not* tagged
* @return {SearchResults}
*/
public tagged(
tags: string[] | string,
{ invert = false } = {},
): SearchResults {
const searchTags = Array.isArray(tags) ? tags : [tags]
const posts: Post[] = []
for (const p of this) {
const m: number = Utils.compareArrays(searchTags, p.tags).length
if ((!invert && m > 0) || (invert && m === 0)) {
posts.push(p)
}
}
return new SearchResults(posts, this.tags, this.options, this.booru)
}
/**
* Returns a SearchResults with images *not* tagged with any of the specified tags (or tag)
* @param {String[]|String} tags The tags (or tag) to blacklist
* @return {SearchResults} The results without any images with the specified tags
*/
public blacklist(tags: string[] | string): SearchResults {
return this.tagged(tags, { invert: true })
}
}