Skip to content

Commit cf661ba

Browse files
committed
feat(bot): add innertube search
1 parent 10a972f commit cf661ba

File tree

2 files changed

+208
-0
lines changed

2 files changed

+208
-0
lines changed

src/types/innertube.d.ts

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
// NOTE: Experimental
2+
// You think i was typing this all out manually? lol no :p
3+
4+
export type InnertubeSearchRequest = {
5+
contents: {
6+
twoColumnSearchResultsRenderer: {
7+
primaryContents: {
8+
sectionListRenderer: {
9+
contents: Array<{
10+
itemSectionRenderer?: {
11+
contents: Array<{
12+
didYouMeanRenderer?: {
13+
didYouMean: {
14+
runs: Array<{
15+
text: string;
16+
}>;
17+
};
18+
correctedQuery: {
19+
runs: Array<{
20+
text: string;
21+
italics: boolean;
22+
}>;
23+
};
24+
correctedQueryEndpoint: {
25+
clickTrackingParams: string;
26+
commandMetadata: {
27+
webCommandMetadata: {
28+
url: string;
29+
webPageType: string;
30+
rootVe: number;
31+
};
32+
};
33+
searchEndpoint: {
34+
query: string;
35+
params: string;
36+
};
37+
};
38+
trackingParams: string;
39+
};
40+
channelRenderer?: {
41+
channelId: string;
42+
title: {
43+
simpleText: string;
44+
};
45+
navigationEndpoint: {
46+
clickTrackingParams: string;
47+
commandMetadata: {
48+
webCommandMetadata: {
49+
url: string;
50+
webPageType: string;
51+
rootVe: number;
52+
apiUrl: string;
53+
};
54+
};
55+
browseEndpoint: {
56+
browseId: string;
57+
canonicalBaseUrl: string;
58+
};
59+
};
60+
thumbnail: {
61+
thumbnails: Array<{
62+
url: string;
63+
width: number;
64+
height: number;
65+
}>;
66+
};
67+
descriptionSnippet?: {
68+
runs: Array<{
69+
text: string;
70+
bold?: boolean;
71+
}>;
72+
};
73+
shortBylineText: {
74+
runs: Array<{
75+
text: string;
76+
navigationEndpoint: {
77+
clickTrackingParams: string;
78+
commandMetadata: {
79+
webCommandMetadata: {
80+
url: string;
81+
webPageType: string;
82+
rootVe: number;
83+
apiUrl: string;
84+
};
85+
};
86+
browseEndpoint: {
87+
browseId: string;
88+
canonicalBaseUrl: string;
89+
};
90+
};
91+
}>;
92+
};
93+
videoCountText: {
94+
accessibility: {
95+
accessibilityData: {
96+
label: string;
97+
};
98+
};
99+
simpleText: string;
100+
};
101+
subscriptionButton: {
102+
subscribed: boolean;
103+
};
104+
subscriberCountText: {
105+
simpleText: string;
106+
};
107+
subscribeButton: {
108+
buttonRenderer: {
109+
style: string;
110+
size: string;
111+
isDisabled: boolean;
112+
text: {
113+
runs: Array<{
114+
text: string;
115+
}>;
116+
};
117+
navigationEndpoint: {
118+
clickTrackingParams: string;
119+
commandMetadata: {
120+
webCommandMetadata: {
121+
url: string;
122+
webPageType: string;
123+
rootVe: number;
124+
};
125+
};
126+
signInEndpoint: {
127+
nextEndpoint: {
128+
clickTrackingParams: string;
129+
commandMetadata: {
130+
webCommandMetadata: {
131+
url: string;
132+
webPageType: string;
133+
rootVe: number;
134+
};
135+
};
136+
searchEndpoint: {
137+
query: string;
138+
params: string;
139+
};
140+
};
141+
continueAction: string;
142+
};
143+
};
144+
trackingParams: string;
145+
};
146+
};
147+
trackingParams: string;
148+
longBylineText: {
149+
runs: Array<{
150+
text: string;
151+
navigationEndpoint: {
152+
clickTrackingParams: string;
153+
commandMetadata: {
154+
webCommandMetadata: {
155+
url: string;
156+
webPageType: string;
157+
rootVe: number;
158+
apiUrl: string;
159+
};
160+
};
161+
browseEndpoint: {
162+
browseId: string;
163+
canonicalBaseUrl: string;
164+
};
165+
};
166+
}>;
167+
};
168+
};
169+
}>;
170+
};
171+
}>;
172+
};
173+
};
174+
};
175+
};
176+
};

src/utils/youtube/search.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// NOTE: Experimental
2+
import type { InnertubeSearchRequest } from "../../types/innertube";
3+
4+
export default async function (query: string) {
5+
try {
6+
const response = await fetch(
7+
"https://www.youtube.com/youtubei/v1/search?prettyPrint=false",
8+
{
9+
headers: {
10+
"X-Goog-Fieldmask":
11+
"contents.twoColumnSearchResultsRenderer.primaryContents.sectionListRenderer.contents.itemSectionRenderer.contents",
12+
},
13+
body: JSON.stringify({
14+
context: {
15+
client: {
16+
clientName: "WEB",
17+
clientVersion: "2.20241212.08.00",
18+
},
19+
},
20+
params: "EgIQAg%3D%3D",
21+
query: query,
22+
}),
23+
method: "POST",
24+
},
25+
);
26+
const data = (await response.json()) as Promise<InnertubeSearchRequest>;
27+
28+
console.dir(data, { depth: null });
29+
} catch (err) {
30+
console.error(err);
31+
}
32+
}

0 commit comments

Comments
 (0)