|
1 | 1 | import { isNullOrBlank } from "../utils"
|
2 |
| -import { ICollections, IIdentify, IProfile, IReleases, VinylAPIImageMap } from "./interface" |
| 2 | +import { ICollections, IIdentify, IProfile, IReleases, IReleaseSet, VinylAPIImageMap } from "./interface" |
3 | 3 |
|
4 | 4 | const API_URL = "https://api.discogs.com"
|
5 | 5 |
|
@@ -29,172 +29,105 @@ export const getProfile = async (username: string, password: string): Promise<IP
|
29 | 29 | return response.json()
|
30 | 30 | }
|
31 | 31 |
|
32 |
| -export const getCollectionWants = async ( |
| 32 | +export const getCollectionAndWants = async ( |
33 | 33 | username: string,
|
34 | 34 | password: string,
|
35 | 35 | imageQuality: boolean,
|
36 | 36 | onProgress?: (page: number, pages: number) => void
|
37 |
| -): Promise<IReleases[]> => { |
38 |
| - let allReleases: IReleases[] = [] |
39 |
| - let url: string | undefined = `${API_URL}/users/${username}/wants?per_page=100` |
| 37 | +): Promise<IReleaseSet> => { |
40 | 38 | const vinylURL = import.meta.env.VITE_VINYL_API_URL
|
41 |
| - |
42 |
| - while (url) { |
43 |
| - const response = await fetch(url, { |
44 |
| - headers: { |
45 |
| - "Content-Type": "application/json", |
46 |
| - Authorization: `Discogs token=${password}`, |
47 |
| - }, |
48 |
| - }) |
49 |
| - |
50 |
| - if (!response.ok) { |
51 |
| - throw new Error("Network response was not ok") |
52 |
| - } |
53 |
| - |
54 |
| - const data: ICollections = await response.json() |
55 |
| - |
56 |
| - let imageMap: Record<number, VinylAPIImageMap> = {} |
57 |
| - if (vinylURL && vinylURL !== "") { |
58 |
| - try { |
59 |
| - const secondaryResponse = await fetch(`${vinylURL}/api/queue`, { |
60 |
| - method: "POST", |
61 |
| - headers: { |
62 |
| - "Content-Type": "application/json", |
63 |
| - }, |
64 |
| - // @ts-expect-error Cheating a bit - converting the reference to keep the same models. |
65 |
| - body: JSON.stringify(data.wants.map((item) => item.basic_information.id) ?? []), |
66 |
| - }) |
67 |
| - |
68 |
| - if (secondaryResponse.ok) { |
69 |
| - const imageData = await secondaryResponse.json() |
70 |
| - |
71 |
| - imageMap = imageData.available.reduce((acc: Record<number, VinylAPIImageMap>, record: any) => { |
72 |
| - acc[record.recordID] = { |
73 |
| - image: record.image, |
74 |
| - imageHigh: record.imageHigh, |
75 |
| - barcode: record.barcode, |
76 |
| - } |
77 |
| - return acc |
78 |
| - }, {}) |
79 |
| - } else { |
80 |
| - console.warn("Vinyl API response was not ok, skipping.") |
81 |
| - } |
82 |
| - } catch (error) { |
83 |
| - console.error("Vinyl API response hit an error, skipping.", error) |
| 39 | + |
| 40 | + const fetchReleases = async ( |
| 41 | + url: string, |
| 42 | + releaseType: 'collection' | 'wants' |
| 43 | + ): Promise<IReleases[]> => { |
| 44 | + let allReleases: IReleases[] = [] |
| 45 | + while (url) { |
| 46 | + const response = await fetch(url, { |
| 47 | + headers: { |
| 48 | + "Content-Type": "application/json", |
| 49 | + Authorization: `Discogs token=${password}`, |
| 50 | + }, |
| 51 | + }) |
| 52 | + |
| 53 | + if (!response.ok) { |
| 54 | + throw new Error("Network response was not ok") |
84 | 55 | }
|
85 |
| - } |
86 | 56 |
|
87 |
| - // @ts-expect-error Cheating a bit - converting the reference to keep the same models. |
88 |
| - const releasesExtraData = data.wants.map((release) => { |
89 |
| - const imageRecord = imageMap[release.basic_information.id] || { |
90 |
| - image: null, |
91 |
| - imageHigh: null, |
92 |
| - barcode: null, |
93 |
| - } |
94 |
| - return { |
95 |
| - ...release, |
96 |
| - image_base64: imageQuality |
97 |
| - ? !isNullOrBlank(imageRecord.imageHigh) |
98 |
| - ? imageRecord.imageHigh |
99 |
| - : imageRecord.image |
100 |
| - : imageRecord.image, |
101 |
| - barcode: imageRecord.barcode, |
| 57 | + const data: ICollections = await response.json() |
| 58 | + |
| 59 | + let imageMap: Record<number, VinylAPIImageMap> = {} |
| 60 | + if (vinylURL && vinylURL !== "") { |
| 61 | + try { |
| 62 | + const secondaryResponse = await fetch(`${vinylURL}/api/queue`, { |
| 63 | + method: "POST", |
| 64 | + headers: { |
| 65 | + "Content-Type": "application/json", |
| 66 | + }, |
| 67 | + body: JSON.stringify( |
| 68 | + // @ts-expect-error Cheating a bit - converting the reference to keep the same models. |
| 69 | + (releaseType === 'wants' ? data.wants : data.releases).map((item) => item.basic_information.id) ?? [] |
| 70 | + ), |
| 71 | + }) |
| 72 | + |
| 73 | + if (secondaryResponse.ok) { |
| 74 | + const imageData = await secondaryResponse.json() |
| 75 | + |
| 76 | + imageMap = imageData.available.reduce((acc: Record<number, VinylAPIImageMap>, record: any) => { |
| 77 | + acc[record.recordID] = { |
| 78 | + image: record.image, |
| 79 | + imageHigh: record.imageHigh, |
| 80 | + barcode: record.barcode, |
| 81 | + } |
| 82 | + return acc |
| 83 | + }, {}) |
| 84 | + } else { |
| 85 | + console.warn("Vinyl API response was not ok, skipping.") |
| 86 | + } |
| 87 | + } catch (error) { |
| 88 | + console.error("Vinyl API response hit an error, skipping.", error) |
| 89 | + } |
102 | 90 | }
|
103 |
| - }) |
104 |
| - |
105 |
| - allReleases = [...allReleases, ...releasesExtraData] |
106 |
| - |
107 |
| - if (onProgress) { |
108 |
| - onProgress(data.pagination.page, data.pagination.pages) |
109 |
| - } |
110 |
| - |
111 |
| - // Set the url to the next page, or undefined if there are no more pages |
112 |
| - url = data.pagination.urls.next |
113 |
| - } |
114 |
| - |
115 |
| - return allReleases |
116 |
| -} |
117 |
| - |
118 |
| -export const getCollectionReleases = async ( |
119 |
| - username: string, |
120 |
| - password: string, |
121 |
| - imageQuality: boolean, |
122 |
| - onProgress?: (page: number, pages: number) => void |
123 |
| -): Promise<IReleases[]> => { |
124 |
| - let allReleases: IReleases[] = [] |
125 |
| - let url: string | undefined = `${API_URL}/users/${username}/collection/folders/0/releases?per_page=100` |
126 |
| - const vinylURL = import.meta.env.VITE_VINYL_API_URL |
127 |
| - |
128 |
| - while (url) { |
129 |
| - const response = await fetch(url, { |
130 |
| - headers: { |
131 |
| - "Content-Type": "application/json", |
132 |
| - Authorization: `Discogs token=${password}`, |
133 |
| - }, |
134 |
| - }) |
135 |
| - |
136 |
| - if (!response.ok) { |
137 |
| - throw new Error("Network response was not ok") |
138 |
| - } |
139 | 91 |
|
140 |
| - const data: ICollections = await response.json() |
141 |
| - |
142 |
| - let imageMap: Record<number, VinylAPIImageMap> = {} |
143 |
| - if (vinylURL && vinylURL !== "") { |
144 |
| - try { |
145 |
| - const secondaryResponse = await fetch(`${vinylURL}/api/queue`, { |
146 |
| - method: "POST", |
147 |
| - headers: { |
148 |
| - "Content-Type": "application/json", |
149 |
| - }, |
150 |
| - body: JSON.stringify(data.releases.map((item) => item.basic_information.id) ?? []), |
151 |
| - }) |
152 |
| - |
153 |
| - if (secondaryResponse.ok) { |
154 |
| - const imageData = await secondaryResponse.json() |
155 |
| - |
156 |
| - imageMap = imageData.available.reduce((acc: Record<number, VinylAPIImageMap>, record: any) => { |
157 |
| - acc[record.recordID] = { |
158 |
| - image: record.image, |
159 |
| - imageHigh: record.imageHigh, |
160 |
| - barcode: record.barcode, |
161 |
| - } |
162 |
| - return acc |
163 |
| - }, {}) |
164 |
| - } else { |
165 |
| - console.warn("Vinyl API response was not ok, skipping.") |
| 92 | + // @ts-expect-error Cheating a bit - converting the reference to keep the same models. |
| 93 | + const releasesExtraData = (releaseType === 'wants' ? data.wants : data.releases).map((release) => { |
| 94 | + const imageRecord = imageMap[release.basic_information.id] || { |
| 95 | + image: null, |
| 96 | + imageHigh: null, |
| 97 | + barcode: null, |
166 | 98 | }
|
167 |
| - } catch (error) { |
168 |
| - console.error("Vinyl API response hit an error, skipping.", error) |
169 |
| - } |
170 |
| - } |
| 99 | + return { |
| 100 | + ...release, |
| 101 | + image_base64: imageQuality |
| 102 | + ? !isNullOrBlank(imageRecord.imageHigh) |
| 103 | + ? imageRecord.imageHigh |
| 104 | + : imageRecord.image |
| 105 | + : imageRecord.image, |
| 106 | + barcode: imageRecord.barcode, |
| 107 | + } |
| 108 | + }) |
171 | 109 |
|
172 |
| - const releasesExtraData = data.releases.map((release) => { |
173 |
| - const imageRecord = imageMap[release.basic_information.id] || { |
174 |
| - image: null, |
175 |
| - imageHigh: null, |
176 |
| - barcode: null, |
177 |
| - } |
178 |
| - return { |
179 |
| - ...release, |
180 |
| - image_base64: imageQuality |
181 |
| - ? !isNullOrBlank(imageRecord.imageHigh) |
182 |
| - ? imageRecord.imageHigh |
183 |
| - : imageRecord.image |
184 |
| - : imageRecord.image, |
185 |
| - barcode: imageRecord.barcode, |
186 |
| - } |
187 |
| - }) |
| 110 | + allReleases = [...allReleases, ...releasesExtraData] |
188 | 111 |
|
189 |
| - allReleases = [...allReleases, ...(releasesExtraData as IReleases[])] |
| 112 | + if (onProgress) { |
| 113 | + onProgress(data.pagination.page, data.pagination.pages) |
| 114 | + } |
190 | 115 |
|
191 |
| - if (onProgress) { |
192 |
| - onProgress(data.pagination.page, data.pagination.pages) |
| 116 | + // @ts-expect-error not sure? |
| 117 | + url = data.pagination.urls.next |
193 | 118 | }
|
194 | 119 |
|
195 |
| - // Set the url to the next page, or undefined if there are no more pages |
196 |
| - url = data.pagination.urls.next |
| 120 | + return allReleases |
197 | 121 | }
|
198 | 122 |
|
199 |
| - return allReleases |
| 123 | + // Fetch wants and collection in parallel |
| 124 | + const [wantsReleases, collectionReleases] = await Promise.all([ |
| 125 | + fetchReleases(`${API_URL}/users/${username}/wants?per_page=100`, 'wants'), |
| 126 | + fetchReleases(`${API_URL}/users/${username}/collection/folders/0/releases?per_page=100`, 'collection'), |
| 127 | + ]) |
| 128 | + |
| 129 | + return { |
| 130 | + collection: collectionReleases, |
| 131 | + wants: wantsReleases, |
| 132 | + } |
200 | 133 | }
|
0 commit comments