Skip to content

Commit 540625f

Browse files
committed
chore(bot): continue db migration
1 parent 4b19414 commit 540625f

File tree

8 files changed

+173
-50
lines changed

8 files changed

+173
-50
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ target/
1010
*.sqlite
1111
*.sqlite3*
1212
*.sql
13-
dbtests.ts
13+
dbtests.ts
14+
perftesting.ts

src/commands.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@ import { PermissionFlagsBits } from "discord-api-types/v8";
1515

1616
import checkIfChannelIdIsValid from "./utils/youtube/checkIfChannelIdIsValid";
1717
import {
18-
addNewChannelToTrack,
1918
addNewGuildToTrackChannel,
20-
checkIfChannelIsAlreadyTracked,
2119
checkIfGuildIsTrackingChannelAlready,
2220
getAllTrackedInGuild,
2321
stopGuildTrackingChannel,
@@ -30,6 +28,10 @@ import {
3028
import getChannelDetails from "./utils/youtube/getChannelDetails";
3129
import { getStreamerId } from "./utils/twitch/getStreamerId";
3230
import { checkIfStreamerIsLive } from "./utils/twitch/checkIfStreamerIsLive";
31+
import {
32+
checkIfChannelIsAlreadyTracked,
33+
addNewChannelToTrack,
34+
} from "./utils/db/youtube";
3335

3436
import client from ".";
3537

src/types/innertube.d.ts renamed to src/types/youtube.d.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,60 @@
1+
export interface YouTubePlaylistResponse {
2+
kind: string;
3+
etag: string;
4+
nextPageToken: string;
5+
items: Array<{
6+
kind: string;
7+
etag: string;
8+
id: string;
9+
snippet: {
10+
publishedAt: string;
11+
channelId: string;
12+
title: string;
13+
description: string;
14+
thumbnails: {
15+
default: {
16+
url: string;
17+
width: number;
18+
height: number;
19+
};
20+
medium: {
21+
url: string;
22+
width: number;
23+
height: number;
24+
};
25+
high: {
26+
url: string;
27+
width: number;
28+
height: number;
29+
};
30+
standard: {
31+
url: string;
32+
width: number;
33+
height: number;
34+
};
35+
maxres: {
36+
url: string;
37+
width: number;
38+
height: number;
39+
};
40+
};
41+
channelTitle: string;
42+
playlistId: string;
43+
position: number;
44+
resourceId: {
45+
kind: string;
46+
videoId: string;
47+
};
48+
videoOwnerChannelTitle: string;
49+
videoOwnerChannelId: string;
50+
};
51+
}>;
52+
pageInfo: {
53+
totalResults: number;
54+
resultsPerPage: number;
55+
};
56+
}
57+
158
export interface InnertubeSearchRequest {
259
contents: {
360
twoColumnSearchResultsRenderer: {

src/utils/database.ts

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -27,51 +27,6 @@ export const pool: Pool = new Pool({
2727
});
2828

2929
// #region YouTube
30-
// These two functions are for checking/adding a new channel to the youtube table
31-
export async function checkIfChannelIsAlreadyTracked(channelId: string) {
32-
const query = `SELECT * FROM youtube WHERE youtube_channel_id = ?`;
33-
34-
try {
35-
const statement = db.prepare(query);
36-
const result = statement.all(channelId);
37-
38-
return result.length > 0;
39-
} catch (err) {
40-
console.error("Error checking if channel is already tracked:", err);
41-
throw err;
42-
}
43-
}
44-
45-
export async function addNewChannelToTrack(channelId: string) {
46-
console.log("Adding channel to track:", channelId);
47-
const res = await fetch(
48-
`https://youtube.googleapis.com/youtube/v3/playlists?part=snippet&id=${channelId.replace("UC", "UU")}&key=${env.youtubeApiKey}`,
49-
);
50-
51-
if (!res.ok) {
52-
return false;
53-
}
54-
55-
const data = await res.json();
56-
const videoId =
57-
data.items?.[0]?.snippet?.thumbnails?.default?.url?.split("/")[4] ||
58-
null;
59-
60-
const query = `INSERT INTO youtube (youtube_channel_id, latest_video_id) VALUES (?, ?)`;
61-
62-
try {
63-
const statement = db.prepare(query);
64-
65-
statement.run(channelId, videoId);
66-
67-
return true;
68-
} catch (err) {
69-
console.error("Error adding channel to track:", err);
70-
71-
return false;
72-
}
73-
}
74-
7530
export async function checkIfGuildIsTrackingChannelAlready(
7631
channelId: string,
7732
guild_id: string,

src/utils/db/init.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ export default async function initTables(): Promise<boolean> {
55
CREATE TABLE IF NOT EXISTS discord (
66
guild_id TEXT PRIMARY KEY,
77
is_dm BOOLEAN NOT NULL DEFAULT FALSE,
8-
allowed_public_sharing BOOLEAN NOT NULL DEFAULT FALSE
8+
allowed_public_sharing BOOLEAN NOT NULL DEFAULT FALSE,
9+
feedr_updates_channel_id TEXT
910
);
1011
`;
1112

src/utils/db/youtube.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import type { dbYouTube } from "../../types/database";
22

33
import { pool } from "../database";
4+
import getSinglePlaylistAndReturnVideoId, {
5+
PlaylistType,
6+
} from "../youtube/getSinglePlaylistAndReturnVideoId";
47

58
export async function dbYouTubeGetAllChannelsToTrack(): Promise<
69
dbYouTube[] | []
@@ -20,3 +23,60 @@ export async function dbYouTubeGetAllChannelsToTrack(): Promise<
2023
return [];
2124
}
2225
}
26+
27+
// These two functions are for checking/adding a new channel to the youtube table
28+
export async function checkIfChannelIsAlreadyTracked(
29+
channelId: string,
30+
): Promise<boolean> {
31+
const query = `SELECT * FROM youtube WHERE youtube_channel_id = ?`;
32+
33+
try {
34+
const client = await pool.connect();
35+
const result = await client.query(query, [channelId]);
36+
37+
return result.rows.length > 0;
38+
} catch (err) {
39+
console.error("Error checking if channel is already tracked:", err);
40+
41+
return false;
42+
}
43+
}
44+
45+
// Before adding a new channel, we need to get the latest video, short and stream ID
46+
export async function addNewChannelToTrack(
47+
channelId: string,
48+
): Promise<boolean> {
49+
console.log("Adding channel to track:", channelId);
50+
51+
const longId = await getSinglePlaylistAndReturnVideoId(
52+
channelId,
53+
PlaylistType.Video,
54+
);
55+
const shortId = await getSinglePlaylistAndReturnVideoId(
56+
channelId,
57+
PlaylistType.Short,
58+
);
59+
const liveId = await getSinglePlaylistAndReturnVideoId(
60+
channelId,
61+
PlaylistType.Stream,
62+
);
63+
64+
const query = `INSERT INTO youtube (youtube_channel_id, latest_video_id, latest_short_id, latest_stream_id) VALUES (?, ?, ?, ?)`;
65+
66+
try {
67+
const client = await pool.connect();
68+
69+
await client.query(query, [
70+
channelId,
71+
longId || null,
72+
shortId || null,
73+
liveId || null,
74+
]);
75+
76+
return true;
77+
} catch (err) {
78+
console.error("Error adding channel to track:", err);
79+
80+
return false;
81+
}
82+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import type { YouTubePlaylistResponse } from "../../types/youtube";
2+
3+
import { env } from "../../config";
4+
5+
export enum PlaylistType {
6+
Video = "video",
7+
Short = "short",
8+
Stream = "stream",
9+
}
10+
11+
const playlistIdPrefixes: Record<PlaylistType, string> = {
12+
[PlaylistType.Video]: "UULF",
13+
[PlaylistType.Short]: "UUSH",
14+
[PlaylistType.Stream]: "UULV",
15+
};
16+
17+
export default async function (
18+
channelId: string,
19+
playlistType?: PlaylistType,
20+
): Promise<string | null> {
21+
const playlistIdPrefix = !playlistType
22+
? "UU"
23+
: playlistIdPrefixes[playlistType];
24+
25+
if (!channelId.startsWith("UC")) {
26+
return null;
27+
}
28+
29+
const playlistId = playlistIdPrefix + channelId.slice(2);
30+
31+
const res = await fetch(
32+
`https://youtube.googleapis.com/youtube/v3/playlists?part=snippet&id=${playlistId}&key=${env.youtubeApiKey}`,
33+
);
34+
35+
if (!res.ok) {
36+
return null;
37+
}
38+
39+
const json = (await res.json()) as YouTubePlaylistResponse;
40+
41+
if (!json.items || json.items.length === 0) {
42+
return null;
43+
}
44+
45+
// Yes this does actually return the video ID, you'll be surprised how weird YouTube's API is
46+
return atob(json.items[0].id).split(".")[1];
47+
}

src/utils/youtube/search.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// NOTE: Experimental
2-
import type { InnertubeSearchRequest } from "../../types/innertube";
2+
import type { InnertubeSearchRequest } from "../../types/youtube";
33

44
export default async function (query: string) {
55
try {

0 commit comments

Comments
 (0)