Skip to content

Commit dc7f2dd

Browse files
committed
Added Husbando Route
1 parent f3520ea commit dc7f2dd

File tree

4 files changed

+445
-0
lines changed

4 files changed

+445
-0
lines changed

src/controllers/v4/images/husbando.js

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import _ from 'lodash';
2+
import createError from 'http-errors';
3+
import Husbandos from '../../../models/schemas/Husbando.js';
4+
import Stats from '../../../models/schemas/Stat.js';
5+
6+
/**
7+
* Retrieves a random husbando and updates system statistics.
8+
*
9+
* @function
10+
* @param {Object} req - Express request object.
11+
* @param {Object} res - Express response object.
12+
* @param {Function} next - Express next middleware function.
13+
*
14+
* @throws {Error} If there is an error during husbando retrieval or database update.
15+
*
16+
* @returns {Object} JSON object containing the random husbando.
17+
* @example
18+
* // Example usage in Express route handler
19+
* getHusbando(req, res, next);
20+
*/
21+
const getHusbando = async (req, res, next) => {
22+
try {
23+
/**
24+
* Extracts character name and anime parameters from the request query.
25+
* @type {Object}
26+
*/
27+
const { name, anime } = req.query;
28+
29+
/**
30+
* Holds the filter object based on the optional character name and anime name parameters.
31+
* @type {Object}
32+
*/
33+
const filter = {};
34+
35+
/**
36+
* Adds conditions to the filter object based on request parameters.
37+
* @type {Object}
38+
*/
39+
if (name) {
40+
const sanitizedName = _.escapeRegExp(name.trim());
41+
filter['name.full'] = { $regex: new RegExp(sanitizedName, 'i') }; // Case-insensitive regex match for the English name
42+
}
43+
44+
if (anime) {
45+
const sanitizedAnime = _.escapeRegExp(anime.trim());
46+
filter['media.nodes[0].title.userPreferred'] = { $regex: new RegExp(sanitizedAnime, 'i') }; // Case-insensitive regex match for anime name
47+
}
48+
49+
/**
50+
* Holds the result of the random husbando retrieval.
51+
* @type {Object}
52+
*/
53+
const [result] = await Husbandos.aggregate([
54+
{ $match: filter }, // Apply filter conditions (if any)
55+
{ $sample: { size: 1 } },
56+
{ $project: { __v: 0 } },
57+
]);
58+
59+
// If no husbando is found, return a 404 error
60+
if (!result) {
61+
return next(createError(404, 'Could not find any matching husbando'));
62+
}
63+
64+
res.status(200).json(result);
65+
66+
// Update system statistics for husbandos
67+
await Stats.findOneAndUpdate({ _id: 'systemstats' }, { $inc: { husbandos: 1 } });
68+
} catch (error) {
69+
/**
70+
* Update system statistics for failed requests.
71+
* @type {Object}
72+
*/
73+
await Stats.findOneAndUpdate({ _id: 'systemstats' }, { $inc: { failed_requests: 1 } });
74+
next(error);
75+
}
76+
};
77+
78+
export default getHusbando;

src/models/schemas/Husbando.js

+248
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
import mongoose from 'mongoose';
2+
3+
const { Schema, model } = mongoose;
4+
5+
/**
6+
* Represents the schema for the Husbando model.
7+
* @class HusbandoSchema
8+
*/
9+
const HusbandoSchema = new Schema({
10+
/**
11+
* The unique identifier for the husbando.
12+
* @type {Number}
13+
*/
14+
_id: { type: Number, required: true },
15+
16+
/**
17+
* The name details of the husbando.
18+
* @type {Object}
19+
*/
20+
name: {
21+
/**
22+
* The first name of the husbando.
23+
* @type {String}
24+
*/
25+
first: { type: String, required: true },
26+
27+
/**
28+
* The middle name of the husbando.
29+
* @type {String}
30+
*/
31+
middle: String,
32+
33+
/**
34+
* The last name of the husbando.
35+
* @type {String}
36+
*/
37+
last: { type: String, required: true },
38+
39+
/**
40+
* The full name of the husbando.
41+
* @type {String}
42+
*/
43+
full: { type: String, required: true },
44+
45+
/**
46+
* The native name of the husbando.
47+
* @type {String}
48+
*/
49+
native: String,
50+
51+
/**
52+
* The user-preferred name of the husbando.
53+
* @type {String}
54+
*/
55+
userPreferred: { type: String, required: true },
56+
57+
/**
58+
* Alternative names for the husbando.
59+
* @type {Array}
60+
*/
61+
alternative: [String],
62+
63+
/**
64+
* Alternative spoiler names for the husbando.
65+
* @type {Array}
66+
*/
67+
alternativeSpoiler: [String],
68+
},
69+
70+
/**
71+
* The image URL associated with the husbando.
72+
* @type {Object}
73+
*/
74+
image: {
75+
/**
76+
* The URL for the large image of the husbando.
77+
* @type {String}
78+
*/
79+
large: String,
80+
medium: String,
81+
},
82+
83+
/**
84+
* The number of favorites for the husbando.
85+
* @type {Number}
86+
*/
87+
favourites: { type: Number, required: true },
88+
89+
/**
90+
* The URL of the AniList page for the husbando.
91+
* @type {String}
92+
*/
93+
siteUrl: { type: String, required: true },
94+
95+
/**
96+
* The description of the husbando.
97+
* @type {String}
98+
*/
99+
description: { type: String, required: true },
100+
101+
/**
102+
* The age of the husbando.
103+
* @type {String}
104+
*/
105+
age: String,
106+
107+
/**
108+
* The gender of the husbando.
109+
* @type {String}
110+
*/
111+
gender: { type: String, required: true },
112+
113+
/**
114+
* The blood type of the husbando.
115+
* @type {String}
116+
*/
117+
bloodType: String,
118+
119+
/**
120+
* The date of birth of the husbando.
121+
* @type {Object}
122+
*/
123+
dateOfBirth: {
124+
/**
125+
* The year of birth for the husbando.
126+
* @type {Number}
127+
*/
128+
year: Number,
129+
130+
/**
131+
* The month of birth for the husbando.
132+
* @type {Number}
133+
*/
134+
month: Number,
135+
136+
/**
137+
* The day of birth for the husbando.
138+
* @type {Number}
139+
*/
140+
day: Number,
141+
},
142+
143+
/**
144+
* The media details associated with the husbando.
145+
* @type {Object}
146+
*/
147+
media: {
148+
/**
149+
* An array of nodes containing information about various media related to the husbando.
150+
* @type {Array}
151+
*/
152+
nodes: [
153+
{
154+
/**
155+
* The unique identifier for the media.
156+
* @type {Number}
157+
*/
158+
id: { type: Number, required: true },
159+
160+
/**
161+
* The unique identifier for the media on MyAnimeList.
162+
* @type {Number}
163+
*/
164+
idMal: { type: Number, required: true },
165+
166+
/**
167+
* The cover image details for the media.
168+
* @type {Object}
169+
*/
170+
coverImage: {
171+
/**
172+
* The URL for the medium-sized cover image of the media.
173+
* @type {String}
174+
*/
175+
medium: { type: String, required: true },
176+
},
177+
178+
/**
179+
* The banner image URL for the media.
180+
* @type {String}
181+
*/
182+
bannerImage: String,
183+
184+
/**
185+
* The title details for the media.
186+
* @type {Object}
187+
*/
188+
title: {
189+
/**
190+
* The romaji title of the media.
191+
* @type {String}
192+
*/
193+
romaji: { type: String, required: true },
194+
195+
/**
196+
* The English title of the media.
197+
* @type {String}
198+
*/
199+
english: { type: String, required: true },
200+
201+
/**
202+
* The native title of the media.
203+
* @type {String}
204+
*/
205+
native: { type: String, required: true },
206+
207+
/**
208+
* The user-preferred title of the media.
209+
* @type {String}
210+
*/
211+
userPreferred: { type: String, required: true },
212+
},
213+
214+
/**
215+
* Synonyms for the media.
216+
* @type {Array}
217+
*/
218+
synonyms: [String],
219+
220+
/**
221+
* The popularity score for the media.
222+
* @type {Number}
223+
*/
224+
popularity: Number,
225+
226+
/**
227+
* The type of the media.
228+
* @type {String}
229+
*/
230+
type: { type: String, required: true },
231+
232+
/**
233+
* The format of the media.
234+
* @type {String}
235+
*/
236+
format: { type: String, required: true },
237+
},
238+
],
239+
},
240+
});
241+
242+
/**
243+
* Represents the model for the Husbando.
244+
* @class Husbando
245+
*/
246+
const Husbando = model('Husbando', HusbandoSchema);
247+
248+
export default Husbando;

0 commit comments

Comments
 (0)