[READ-ONLY] Mirror of https://github.com/flo-bit/skywatched. review movies and tv shows, based on at proto
skywatched.app
5.5 kB
217 lines
1import { env } from '$env/dynamic/private';
2
3import type { Agent } from '@atproto/api';
4
5export type Kind = 'movie' | 'tv';
6
7export async function searchMulti(query: string) {
8 const apiUrl = `https://api.themoviedb.org/3/search/multi?query=${query}&include_adult=false&language=en-US&page=1`;
9 const options = {
10 method: 'GET',
11 headers: {
12 accept: 'application/json',
13 Authorization: `Bearer ${env.TMDB_API_KEY}`
14 }
15 };
16
17 const response = await fetch(apiUrl, options);
18 const data = await response.json();
19
20 return data.results;
21}
22
23export async function getDetails(id: number, kind: Kind) {
24 const url = `https://api.themoviedb.org/3/${kind}/${id}?language=en-US`;
25 const options = {
26 method: 'GET',
27 headers: {
28 accept: 'application/json',
29 Authorization: `Bearer ${env.TMDB_API_KEY}`
30 }
31 };
32
33 const response = await fetch(url, options);
34 const data = await response.json();
35
36 return data;
37}
38
39export async function getTrailer(id: number, kind: Kind): Promise<string | null> {
40 const url = `https://api.themoviedb.org/3/${kind}/${id}/videos?language=en-US`;
41 const options = {
42 method: 'GET',
43 headers: {
44 accept: 'application/json',
45 Authorization: `Bearer ${env.TMDB_API_KEY}`
46 }
47 };
48
49 const response = await fetch(url, options);
50 const data = await response.json();
51
52 let trailer = data.results?.find(
53 // eslint-disable-next-line @typescript-eslint/no-explicit-any
54 (video: any) => video.site === 'YouTube' && video.type === 'Trailer' && video.official
55 );
56
57 if (!trailer) {
58 trailer = data.results?.find(
59 // eslint-disable-next-line @typescript-eslint/no-explicit-any
60 (video: any) => video.site === 'YouTube' && video.type === 'Trailer'
61 );
62 }
63
64 return trailer?.key ?? null;
65}
66
67export async function getRecommendations(id: number, kind: Kind) {
68 const url = `https://api.themoviedb.org/3/${kind}/${id}/recommendations?language=en-US`;
69 const options = {
70 method: 'GET',
71 headers: {
72 accept: 'application/json',
73 Authorization: `Bearer ${env.TMDB_API_KEY}`
74 }
75 };
76
77 const response = await fetch(url, options);
78 const data = await response.json();
79
80 return data.results;
81}
82
83export async function getWatchProviders(id: number, kind: Kind) {
84 const url = `https://api.themoviedb.org/3/${kind}/${id}/watch/providers?language=en-US`;
85 const options = {
86 method: 'GET',
87 headers: {
88 accept: 'application/json',
89 Authorization: `Bearer ${env.TMDB_API_KEY}`
90 }
91 };
92
93 const response = await fetch(url, options);
94 const data = await response.json();
95
96 return data.results;
97}
98
99export async function getWatchedMoviesIdsFromPDS(agent: Agent, did: string) {
100 const allRecords = await agent.com.atproto.repo.listRecords({
101 repo: did,
102 collection: 'my.skylights.rel'
103 });
104
105 const movies = allRecords.data.records.filter((record) => record.value.item.ref === 'tmdb:m');
106
107 return new Map(
108 movies.map((movie) => [
109 parseInt(movie.value.item.value ?? '0'),
110 {
111 rating: movie.value.rating.value / 2,
112 ratingText: movie.value.note?.value,
113 updatedAt: movie.value.note?.updatedAt ?? movie.value.rating.createdAt
114 }
115 ])
116 );
117}
118
119export async function getWatchedShowsIdsFromPDS(agent: Agent, did: string) {
120 const allRecords = await agent.com.atproto.repo.listRecords({
121 repo: did,
122 collection: 'my.skylights.rel'
123 });
124
125 const shows = allRecords.data.records.filter((record) => record.value.item.ref === 'tmdb:s');
126
127 return new Map(
128 shows.map((show) => [
129 parseInt(show.value.item.value ?? '0'),
130 {
131 rating: show.value.rating.value / 2,
132 ratingText: show.value.note?.value,
133 updatedAt: show.value.note?.updatedAt ?? show.value.rating.createdAt
134 }
135 ])
136 );
137}
138
139export async function getCast(id: number, kind: Kind) {
140 const url = `https://api.themoviedb.org/3/${kind}/${id}/credits?language=en-US`;
141 const options = {
142 method: 'GET',
143 headers: {
144 accept: 'application/json',
145 Authorization: `Bearer ${env.TMDB_API_KEY}`
146 }
147 };
148
149 const response = await fetch(url, options);
150 const data = await response.json();
151
152 return data.cast;
153}
154
155export async function getPopularMovies() {
156 const url = `https://api.themoviedb.org/3/movie/popular?language=en-US&page=1`;
157 const options = {
158 method: 'GET',
159 headers: {
160 accept: 'application/json',
161 Authorization: `Bearer ${env.TMDB_API_KEY}`
162 }
163 };
164
165 const response = await fetch(url, options);
166 const data = await response.json();
167
168 return data.results;
169}
170
171export async function getPopularShows() {
172 const url = `https://api.themoviedb.org/3/tv/popular?language=en-US&page=1`;
173 const options = {
174 method: 'GET',
175 headers: {
176 accept: 'application/json',
177 Authorization: `Bearer ${env.TMDB_API_KEY}`
178 }
179 };
180
181 const response = await fetch(url, options);
182 const data = await response.json();
183
184 return data.results;
185}
186
187export async function getPersonDetails(personId: number) {
188 const url = `https://api.themoviedb.org/3/person/${personId}?language=en-US`;
189 const options = {
190 method: 'GET',
191 headers: {
192 accept: 'application/json',
193 Authorization: `Bearer ${env.TMDB_API_KEY}`
194 }
195 };
196
197 const response = await fetch(url, options);
198 const data = await response.json();
199
200 return data;
201}
202
203export async function getCombinedCredits(personId: number) {
204 const url = `https://api.themoviedb.org/3/person/${personId}/combined_credits?language=en-US`;
205 const options = {
206 method: 'GET',
207 headers: {
208 accept: 'application/json',
209 Authorization: `Bearer ${env.TMDB_API_KEY}`
210 }
211 };
212
213 const response = await fetch(url, options);
214 const data = await response.json();
215
216 return data;
217}