import type { NarouSearchResult, UserSearchResult, } from "./narou-search-results.js"; import type { Join } from "./util/type.js"; export const RankingType = { Daily: "d", Weekly: "w", Monthly: "m", Quarterly: "q", } as const; export type RankingType = (typeof RankingType)[keyof typeof RankingType]; /** * すべてのAPIで共通のクエリパラメータ */ export interface ParamsBase { /** * gzip圧縮してgzipファイルとして返します。 * gzip圧縮レベルを1~5で指定できます。 * 転送量上限を減らすためにも推奨 */ gzip?: GzipLevel; /** * 出力形式を指定 * 本ライブラリはJSONとJSONPのみ対応 */ out?: "json" | "jsonp"; } /** * 検索APIで共通のクエリパラメータ */ export interface ParamsBaseWithOrder extends ParamsBase { /** * 出力する項目を個別に指定できます。未指定時は全項目出力されます。 * 転送量軽減のため、このパラメータの使用が推奨されます。 */ of?: string; /** * 最大出力数を指定できます。指定しない場合は20件になります。 */ lim?: number; /** 表示開始位置の指定です。 */ st?: number; /** 出力順序を指定できます。 */ order?: TOrder; } /** * メソッドにパラメータを指定する際のヘルパー。 * @see https://dev.syosetu.com/man/api/ * @see https://dev.syosetu.com/xman/atom/ */ export interface SearchParams extends ParamsBaseWithOrder { word?: string; notword?: string; title?: BooleanNumber; ex?: BooleanNumber; keyword?: BooleanNumber; wname?: BooleanNumber; biggenre?: Join | BigGenre; notbiggenre?: Join | BigGenre; genre?: Join | Genre; notgenre?: Join | Genre; userid?: Join | number; nocgenre?: Join | R18Site; notnocgenre?: Join | R18Site; xid?: Join | number; isr15?: BooleanNumber; isbl?: BooleanNumber; isgl?: BooleanNumber; iszankoku?: BooleanNumber; istensei?: BooleanNumber; istenni?: BooleanNumber; istt?: BooleanNumber; notr15?: BooleanNumber; notbl?: BooleanNumber; notgl?: BooleanNumber; notzankoku?: BooleanNumber; nottensei?: BooleanNumber; nottenni?: BooleanNumber; minlen?: number; maxlen?: number; length?: number | Join; kaiwaritu?: number | string; sasie?: number | string; mintime?: number; maxtime?: number; time?: number | string; ncode?: string | Join; type?: NovelTypeParam; buntai?: BuntaiParam | Join; stop?: StopParam; ispickup?: typeof BooleanNumber.True; lastup?: string; lastupdate?: string; opt?: Join; } export interface RankingParams extends ParamsBase { rtype: `${string}-${RankingType}`; } export interface RankingHistoryParams extends ParamsBase { ncode: string; } /** * ユーザー検索パラメータ */ export interface UserSearchParams extends ParamsBaseWithOrder { /** 単語を指定できます。半角または全角スペースで区切るとAND抽出になります。部分一致でHITします。検索の対象はユーザ名とユーザ名のフリガナです。 */ word?: string; /** 含みたくない単語を指定できます。スペースで区切ることにより含ませない単語を増やせます。部分一致で除外されます。除外の対象はユーザ名とユーザ名のフリガナです。 */ notword?: string; /** ユーザIDで抽出可能。 */ userid?: number; /** 抽出するユーザのユーザ名のフリガナの頭文字を指定できます。頭文字はユーザ名のフリガナをひらがなに変換し、最初の1文字が「ぁ」~「ん」の場合に対象となります。 */ name1st?: string; /** 抽出するユーザの小説投稿数の下限を指定できます。小説投稿件数が指定された数値以上のユーザを抽出します。 */ minnovel?: number; /** 抽出するユーザの小説投稿数の上限を指定できます。小説投稿件数が指定された数値以下のユーザを抽出します。 */ maxnovel?: number; /** 抽出するユーザのレビュー投稿数の下限を指定できます。レビュー投稿件数が指定された数値以上のユーザを抽出します。 */ minreview?: number; /** 抽出するユーザのレビュー投稿数の上限を指定できます。レビュー投稿件数が指定された数値以下のユーザを抽出します。 */ maxreview?: number; } export const BooleanNumber = { True: 1, False: 0, } as const; export type BooleanNumber = (typeof BooleanNumber)[keyof typeof BooleanNumber]; export type SearchResultFieldNames = keyof NarouSearchResult; /** * なろう小説APIのofパラメータに指定できる出力する項目 * @see https://dev.syosetu.com/man/api/#output */ export const Fields = { /** 小説名 */ title: "t", /** Nコード */ ncode: "n", /** 作者のユーザID(数値) */ userid: "u", /** 作者名 */ writer: "w", /** 小説のあらすじ */ story: "s", /** 大ジャンル */ biggenre: "bg", /** ジャンル */ genre: "g", /** キーワード */ keyword: "k", /** 初回掲載日 */ general_firstup: "gf", /** 最終掲載日 */ general_lastup: "gl", /** 連載の場合は1、短編の場合は2 */ noveltype: "nt", /** 短編小説と完結済小説は0となっています。連載中は1です。 */ end: "e", /** 全掲載部分数 */ general_all_no: "ga", /** 小説文字数 */ length: "l", /** 読了時間(分単位) */ time: "ti", /** 長期連載停止中 */ isstop: "i", /** 登録必須キーワードに「R15」が含まれる場合は1、それ以外は0です。 */ isr15: "isr", /** 登録必須キーワードに「ボーイズラブ」が含まれる場合は1、それ以外は0です。 */ isbl: "ibl", /** 登録必須キーワードに「ガールズラブ」が含まれる場合は1、それ以外は0です。 */ isgl: "igl", /** 登録必須キーワードに「残酷な描写あり」が含まれる場合は1、それ以外は0です。 */ iszankoku: "izk", /** 登録必須キーワードに「異世界転生」が含まれる場合は1、それ以外は0です。 */ istensei: "its", /** 登録必須キーワードに「異世界転移」が含まれる場合は1、それ以外は0です。 */ istenni: "iti", /** 総合評価ポイント */ global_point: "gp", /** 日間ポイント */ daily_point: "dp", /** 週間ポイント */ weekly_point: "wp", /** 月間ポイント */ monthly_point: "mp", /** 四半期ポイント */ quarter_point: "qp", /** 年間ポイント */ yearly_point: "yp", /** ブックマーク数 */ fav_novel_cnt: "f", /** 感想数 */ impression_cnt: "imp", /** レビュー数 */ review_cnt: "r", /** 評価ポイント */ all_point: "a", /** 評価者数 */ all_hyoka_cnt: "ah", /** 挿絵の数 */ sasie_cnt: "sa", /** 会話率 */ kaiwaritu: "ka", /** 小説の更新日時 */ novelupdated_at: "nu", /** * 最終更新日時 * システム用で小説更新時とは関係ありません */ updated_at: "ua", } as const; export type Fields = (typeof Fields)[keyof Omit< NarouSearchResult, "novel_type" | "weekly_unique" | "nocgenre" >]; /** * なろうR18小説APIのofパラメータに指定できる出力する項目 * @see https://dev.syosetu.com/xman/api/#output */ export const R18Fields = { /** 小説名 */ title: "t", /** Nコード */ ncode: "n", /** 作者のユーザID(数値) */ userid: "u", /** 作者名 */ writer: "w", /** 小説のあらすじ */ story: "s", /** 掲載サイト */ nocgenre: "ng", /** キーワード */ keyword: "k", /** 初回掲載日 */ general_firstup: "gf", /** 最終掲載日 */ general_lastup: "gl", /** 連載の場合は1、短編の場合は2 */ noveltype: "nt", /** 短編小説と完結済小説は0となっています。連載中は1です。 */ end: "e", /** 全掲載部分数 */ general_all_no: "ga", /** 小説文字数 */ length: "l", /** 読了時間(分単位) */ time: "ti", /** 長期連載停止中 */ isstop: "i", /** 登録必須キーワードに「ボーイズラブ」が含まれる場合は1、それ以外は0です。 */ isbl: "ibl", /** 登録必須キーワードに「ガールズラブ」が含まれる場合は1、それ以外は0です。 */ isgl: "igl", /** 登録必須キーワードに「残酷な描写あり」が含まれる場合は1、それ以外は0です。 */ iszankoku: "izk", /** 登録必須キーワードに「異世界転生」が含まれる場合は1、それ以外は0です。 */ istensei: "its", /** 登録必須キーワードに「異世界転移」が含まれる場合は1、それ以外は0です。 */ istenni: "iti", /** 総合評価ポイント */ global_point: "gp", /** 日間ポイント */ daily_point: "dp", /** 週間ポイント */ weekly_point: "wp", /** 月間ポイント */ monthly_point: "mp", /** 四半期ポイント */ quarter_point: "qp", /** 年間ポイント */ yearly_point: "yp", /** R18ブックマーク数 */ fav_novel_cnt: "f", /** 感想数 */ impression_cnt: "imp", /** レビュー数 */ review_cnt: "r", /** 評価ポイント */ all_point: "a", /** 評価者数 */ all_hyoka_cnt: "ah", /** 挿絵の数 */ sasie_cnt: "sa", /** 会話率 */ kaiwaritu: "ka", /** 小説の更新日時 */ novelupdated_at: "nu", /** * 最終更新日時 * システム用で小説更新時とは関係ありません */ updated_at: "ua", } as const; export type R18Fields = (typeof R18Fields)[keyof Omit< NarouSearchResult, "novel_type" | "weekly_unique" | "biggenre" | "genre" | "isr15" >]; /** * オプション項目 */ export const OptionalFields = { /** * 週間ユニークユーザ[項目名:weekly_unique]が追加されます。 * 週間ユニークユーザは前週の日曜日から土曜日分のユニークの合計です。 * 毎週火曜日早朝に更新されます。 */ weekly_unique: "weekly", } as const; export type OptionalFields = (typeof OptionalFields)[keyof Pick< NarouSearchResult, "weekly_unique" >]; /** * ユーザ検索APIのofパラメータに指定できる出力する項目 * @see https://dev.syosetu.com/man/userapi/#output */ export const UserFields = { /** ユーザID */ userid: "u", /** ユーザ名 */ name: "n", /** ユーザ名のフリガナ */ yomikata: "y", /** ユーザ名のフリガナの頭文字 */ name1st: "1", /** 小説投稿数 */ novel_cnt: "nc", /** レビュー投稿数 */ review_cnt: "rc", /** 小説累計文字数 */ novel_length: "nl", /** 総合評価ポイントの合計 */ sum_global_point: "sg", } as const; export type UserFields = (typeof UserFields)[keyof UserSearchResult]; /** * 出力順序 */ export const Order = { /** ブックマーク数の多い順 */ FavoriteNovelCount: "favnovelcnt", /** レビュー数の多い順 */ ReviewCount: "reviewcnt", /** 総合ポイントの高い順 */ HyokaDesc: "hyoka", /** 総合ポイントの低い順 */ HyokaAsc: "hyokaasc", /** 感想の多い順 */ ImpressionCount: "impressioncnt", /** 評価者数の多い順 */ HyokaCountDesc: "hyokacnt", /** 評価者数の少ない順 */ HyokaCountAsc: "hyokacntasc", /** 週間ユニークユーザの多い順 */ Weekly: "weekly", /** 小説本文の文字数が多い順 */ LengthDesc: "lengthdesc", /** 小説本文の文字数が少ない順 */ LengthAsc: "lengthasc", /** Nコードが新しい順 */ NCodeDesc: "ncodedesc", /** 新着更新順 */ New: "new", /** 古い順 */ Old: "old", /** 日間ポイントの高い順 */ DailyPoint: "dailypoint", /** 週間ポイントの高い順 */ WeeklyPoint: "weeklypoint", /** 月間ポイントの高い順 */ MonthlyPoint: "monthlypoint", /** 四半期ポイントの高い順 */ QuarterPoint: "quarterpoint", /** 年間ポイントの高い順 */ YearlyPoint: "yearlypoint", /** 初回掲載順 */ GeneralFirstUp: "generalfirstup", } as const; export type Order = (typeof Order)[keyof typeof Order]; /** R18掲載サイト */ export const R18Site = { /** ノクターンノベルズ(男性向け) */ Nocturne: 1, /** ムーンライトノベルズ(女性向け) */ MoonLight: 2, /** ムーンライトノベルズ(BL) */ MoonLightBL: 3, /** ミッドナイトノベルズ(大人向け) */ Midnight: 4, } as const; export type R18Site = (typeof R18Site)[keyof typeof R18Site]; /** R18掲載サイト表記ヘルパー */ export const R18SiteNotation: { readonly [K in R18Site]: string } = { [R18Site.Nocturne]: "ノクターンノベルズ(男性向け)", [R18Site.MoonLight]: "ムーンライトノベルズ(女性向け)", [R18Site.MoonLightBL]: "ムーンライトノベルズ(BL)", [R18Site.Midnight]: "ミッドナイトノベルズ(大人向け)", } as const; /** 大ジャンル */ export const BigGenre = { /** 恋愛 */ Renai: 1, /** ファンタジー */ Fantasy: 2, /** 文芸 */ Bungei: 3, /** SF */ Sf: 4, /** その他 */ Sonota: 99, /** ノンジャンル */ NonGenre: 98, } as const; export type BigGenre = (typeof BigGenre)[keyof typeof BigGenre]; /** 大ジャンル表記ヘルパー */ export const BigGenreNotation: { readonly [K in BigGenre]: string } = { [BigGenre.Renai]: "恋愛", [BigGenre.Fantasy]: "ファンタジー", [BigGenre.Bungei]: "文芸", [BigGenre.Sf]: "SF", [BigGenre.Sonota]: "その他", [BigGenre.NonGenre]: "ノンジャンル", } as const; /** ジャンル */ export const Genre = { /** 異世界〔恋愛〕*/ RenaiIsekai: 101, /** 現実世界〔恋愛〕*/ RenaiGenjitsusekai: 102, /** ハイファンタジー〔ファンタジー〕*/ FantasyHigh: 201, /** ローファンタジー〔ファンタジー〕*/ FantasyLow: 202, /** 純文学〔文芸〕*/ BungeiJyunbungei: 301, /** ヒューマンドラマ〔文芸〕*/ BungeiHumanDrama: 302, /** 歴史〔文芸〕*/ BungeiHistory: 303, /** 推理〔文芸〕*/ BungeiSuiri: 304, /** ホラー〔文芸〕*/ BungeiHorror: 305, /** アクション〔文芸〕*/ BungeiAction: 306, /** コメディー〔文芸〕*/ BungeiComedy: 307, /** VRゲーム〔SF〕*/ SfVrgame: 401, /** 宇宙〔SF〕*/ SfSpace: 402, /** 空想科学〔SF〕*/ SfKuusoukagaku: 403, /** パニック〔SF〕*/ SfPanic: 404, /** 童話〔その他〕*/ SonotaDouwa: 9901, /** 詩〔その他〕*/ SonotaShi: 9902, /** エッセイ〔その他〕*/ SonotaEssei: 9903, /** リプレイ〔その他〕*/ SonotaReplay: 9904, /** その他〔その他〕 */ SonotaSonota: 9999, /** ノンジャンル〔ノンジャンル〕*/ NonGenre: 9801, } as const; export type Genre = (typeof Genre)[keyof typeof Genre]; /** ジャンル表記ヘルパー */ export const GenreNotation: { readonly [K in Genre]: string } = { [Genre.RenaiIsekai]: "異世界〔恋愛〕", [Genre.RenaiGenjitsusekai]: "現実世界〔恋愛〕", [Genre.FantasyHigh]: "ハイファンタジー〔ファンタジー〕", [Genre.FantasyLow]: "ローファンタジー〔ファンタジー〕", [Genre.BungeiJyunbungei]: "純文学〔文芸〕", [Genre.BungeiHumanDrama]: "ヒューマンドラマ〔文芸〕", [Genre.BungeiHistory]: "歴史〔文芸〕", [Genre.BungeiSuiri]: "推理〔文芸〕", [Genre.BungeiHorror]: "ホラー〔文芸〕", [Genre.BungeiAction]: "アクション〔文芸〕", [Genre.BungeiComedy]: "コメディー〔文芸〕", [Genre.SfVrgame]: "VRゲーム〔SF〕", [Genre.SfSpace]: "宇宙〔SF〕", [Genre.SfKuusoukagaku]: "空想科学〔SF〕", [Genre.SfPanic]: "パニック〔SF〕", [Genre.SonotaDouwa]: "童話〔その他〕", [Genre.SonotaShi]: "詩〔その他〕", [Genre.SonotaEssei]: "エッセイ〔その他〕", [Genre.SonotaReplay]: "リプレイ〔その他〕", [Genre.SonotaSonota]: "その他〔その他〕", [Genre.NonGenre]: "ノンジャンル〔ノンジャンル〕", } as const; /** 文体指定 */ export const BuntaiParam = { /** 字下げされておらず、連続改行が多い作品 */ NoJisageKaigyouOoi: 1, /** 字下げされていないが、改行数は平均な作品 */ NoJisageKaigyoHutsuu: 2, /** 字下げが適切だが、連続改行が多い作品 */ JisageKaigyoOoi: 4, /** 字下げが適切でかつ改行数も平均な作品 */ JisageKaigyoHutsuu: 6, } as const; export type BuntaiParam = (typeof BuntaiParam)[keyof typeof BuntaiParam]; /** 連載停止中指定 */ export const StopParam = { /** 長期連載停止中を除きます */ NoStopping: 1, /** 長期連載停止中のみ取得します */ Stopping: 2, } as const; export type StopParam = (typeof StopParam)[keyof typeof StopParam]; /** 小説タイプ指定 */ export const NovelTypeParam = { /** 短編 */ Short: "t", /** 連載中 */ RensaiNow: "r", /** 完結済連載小説 */ RensaiEnd: "er", /** すべての連載小説(連載中および完結済) */ Rensai: "re", /** 短編と完結済連載小説 */ ShortAndRensai: "ter", } as const; export type NovelTypeParam = (typeof NovelTypeParam)[keyof typeof NovelTypeParam]; /** 日付指定パラメータ */ export const DateParam = { ThisWeek: "thisweek", LastWeek: "lastweek", SevenDays: "sevenday", ThisMonth: "thismonth", LastMonth: "lastmonth", }; export type DateParam = (typeof DateParam)[keyof typeof DateParam]; export const UserOrder = { /** ユーザIDの新しい順 */ New: "new", /** 小説投稿数の多い順 */ NovelCount: "novelcnt", /** レビュー投稿数の多い順 */ ReviewCount: "reviewcnt", /** 小説累計文字数の多い順 */ NovelLength: "novellength", /** 総合評価ポイントの合計の多い順 */ SumGlobalPoint: "sumglobalpoint", /** ユーザIDの古い順 */ Old: "old", } as const; export type UserOrder = (typeof UserOrder)[keyof typeof UserOrder]; export type GzipLevel = 0 | 1 | 2 | 3 | 4 | 5;