pstream is dead; long live pstream taciturnaxolotl.github.io/pstream-ng/
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

disable collection/group syncing

Pas 387982d2 6e518450

+140 -138
+140 -138
src/stores/trakt/TraktBookmarkSyncer.tsx
··· 4 4 import { getPosterForMedia } from "@/backend/metadata/tmdb"; 5 5 import { useBookmarkStore } from "@/stores/bookmarks"; 6 6 import { useTraktAuthStore } from "@/stores/trakt/store"; 7 - import { modifyBookmarks } from "@/utils/bookmarkModifications"; 8 7 import { traktService } from "@/utils/trakt"; 9 - import { TraktContentData, TraktList } from "@/utils/traktTypes"; 8 + import { TraktContentData } from "@/utils/traktTypes"; 10 9 11 10 const TRAKT_SYNC_INTERVAL_MS = 5 * 60 * 1000; // 5 min 12 11 const INITIAL_SYNC_DELAY_MS = 2000; // Re-sync after backend restore 13 12 14 - function listId(list: TraktList): string { 15 - return list.ids.slug ?? String(list.ids.trakt); 16 - } 17 - 18 - async function findListByName( 19 - username: string, 20 - groupName: string, 21 - ): Promise<TraktList | null> { 22 - const lists = await traktService.getLists(username); 23 - return lists.find((l) => l.name === groupName) ?? null; 24 - } 25 - 26 - async function ensureListExists( 27 - username: string, 28 - groupName: string, 29 - ): Promise<TraktList | null> { 30 - const existing = await findListByName(username, groupName); 31 - if (existing) return existing; 32 - try { 33 - return await traktService.createList(username, groupName); 34 - } catch { 35 - return null; 36 - } 37 - } 13 + // Collections/groups sync disabled for now - bookmarks only sync to watchlist 14 + // import { modifyBookmarks } from "@/utils/bookmarkModifications"; 15 + // import { TraktList } from "@/utils/traktTypes"; 16 + // function listId(list: TraktList): string { 17 + // return list.ids.slug ?? String(list.ids.trakt); 18 + // } 19 + // async function findListByName( 20 + // username: string, 21 + // groupName: string, 22 + // ): Promise<TraktList | null> { 23 + // const lists = await traktService.getLists(username); 24 + // return lists.find((l) => l.name === groupName) ?? null; 25 + // } 26 + // async function ensureListExists( 27 + // username: string, 28 + // groupName: string, 29 + // ): Promise<TraktList | null> { 30 + // const existing = await findListByName(username, groupName); 31 + // if (existing) return existing; 32 + // try { 33 + // return await traktService.createList(username, groupName); 34 + // } catch { 35 + // return null; 36 + // } 37 + // } 38 38 39 39 export function TraktBookmarkSyncer() { 40 40 const { traktUpdateQueue, removeTraktUpdateItem, replaceBookmarks } = 41 41 useBookmarkStore(); 42 - const { accessToken, user } = useTraktAuthStore(); 42 + const { accessToken } = useTraktAuthStore(); 43 43 const isSyncingRef = useRef(false); 44 44 const [hydrated, setHydrated] = useState(false); 45 45 ··· 50 50 const processQueue = async () => { 51 51 const queue = [...traktUpdateQueue]; 52 52 if (queue.length === 0) return; 53 - 54 - const slug = user?.ids?.slug; 55 - const hasLists = Boolean(slug); 56 53 57 54 for (const item of queue) { 58 55 removeTraktUpdateItem(item.id); ··· 70 67 71 68 if (item.action === "add") { 72 69 await traktService.addToWatchlist(contentData); 73 - if (hasLists) { 74 - const newGroups = item.group ?? []; 75 - const prevGroups = item.previousGroup ?? []; 70 + // Collections sync disabled - bookmarks only sync to watchlist 71 + // if (hasLists) { 72 + // const newGroups = item.group ?? []; 73 + // const prevGroups = item.previousGroup ?? []; 76 74 77 - // Remove from Trakt lists that the bookmark no longer belongs to 78 - const groupsToRemove = prevGroups.filter( 79 - (g) => !newGroups.includes(g), 80 - ); 81 - for (const groupName of groupsToRemove) { 82 - const list = await findListByName(slug!, groupName); 83 - if (list) { 84 - await traktService.removeFromList(slug!, listId(list), [ 85 - contentData, 86 - ]); 87 - } 88 - } 75 + // // Remove from Trakt lists that the bookmark no longer belongs to 76 + // const groupsToRemove = prevGroups.filter( 77 + // (g) => !newGroups.includes(g), 78 + // ); 79 + // for (const groupName of groupsToRemove) { 80 + // const list = await findListByName(slug!, groupName); 81 + // if (list) { 82 + // await traktService.removeFromList(slug!, listId(list), [ 83 + // contentData, 84 + // ]); 85 + // } 86 + // } 89 87 90 - // Add to Trakt lists that are new 91 - const groupsToAdd = newGroups.filter( 92 - (g) => !prevGroups.includes(g), 93 - ); 94 - for (const groupName of groupsToAdd) { 95 - const list = await ensureListExists(slug!, groupName); 96 - if (list) { 97 - await traktService.addToList(slug!, listId(list), [ 98 - contentData, 99 - ]); 100 - } 101 - } 102 - } 88 + // // Add to Trakt lists that are new 89 + // const groupsToAdd = newGroups.filter( 90 + // (g) => !prevGroups.includes(g), 91 + // ); 92 + // for (const groupName of groupsToAdd) { 93 + // const list = await ensureListExists(slug!, groupName); 94 + // if (list) { 95 + // await traktService.addToList(slug!, listId(list), [ 96 + // contentData, 97 + // ]); 98 + // } 99 + // } 100 + // } 103 101 } else if (item.action === "delete") { 104 102 await traktService.removeFromWatchlist(contentData); 105 - if (hasLists && item.group?.length) { 106 - for (const groupName of item.group) { 107 - const list = await findListByName(slug!, groupName); 108 - if (list) { 109 - await traktService.removeFromList(slug!, listId(list), [ 110 - contentData, 111 - ]); 112 - } 113 - } 114 - } 103 + // Collections sync disabled - bookmarks only sync to watchlist 104 + // if (hasLists && item.group?.length) { 105 + // for (const groupName of item.group) { 106 + // const list = await findListByName(slug!, groupName); 107 + // if (list) { 108 + // await traktService.removeFromList(slug!, listId(list), [ 109 + // contentData, 110 + // ]); 111 + // } 112 + // } 113 + // } 115 114 } 116 115 } catch (error) { 117 116 console.error("Failed to sync bookmark to Trakt", error); ··· 120 119 }; 121 120 122 121 processQueue(); 123 - }, [accessToken, user?.ids?.slug, traktUpdateQueue, removeTraktUpdateItem]); 122 + }, [accessToken, traktUpdateQueue, removeTraktUpdateItem]); 124 123 125 - // Push local bookmarks to Trakt (watchlist + groups) 124 + // Push local bookmarks to Trakt watchlist (TODO implement collections/groups sync) 126 125 const syncBookmarksToTrakt = useCallback(async () => { 127 126 if (!accessToken || isSyncingRef.current) return; 128 - const slug = useTraktAuthStore.getState().user?.ids?.slug; 129 - if (!slug) return; 127 + // const slug = useTraktAuthStore.getState().user?.ids?.slug; 128 + // if (!slug) return; 130 129 isSyncingRef.current = true; 131 130 try { 132 131 if (!useTraktAuthStore.getState().user) { 133 132 await traktService.getUserProfile(); 134 133 } 135 134 const bookmarks = useBookmarkStore.getState().bookmarks; 135 + 136 136 for (const [tmdbId, b] of Object.entries(bookmarks)) { 137 137 try { 138 138 const contentData: TraktContentData = { ··· 142 142 type: b.type === "movie" ? "movie" : "show", 143 143 }; 144 144 await traktService.addToWatchlist(contentData); 145 - if (b.group?.length) { 146 - for (const groupName of b.group) { 147 - const list = await ensureListExists(slug, groupName); 148 - if (list) { 149 - await traktService.addToList(slug, listId(list), [contentData]); 150 - } 151 - } 152 - } 145 + // Collections sync disabled - bookmarks only sync to watchlist 146 + // if (b.group?.length) { 147 + // for (const groupName of b.group) { 148 + // const list = await ensureListExists(slug, groupName); 149 + // if (list) { 150 + // await traktService.addToList(slug, listId(list), [contentData]); 151 + // } 152 + // } 153 + // } 153 154 } catch (err) { 154 155 console.warn("Failed to push bookmark to Trakt:", tmdbId, err); 155 156 } ··· 192 193 193 194 replaceBookmarks(merged); 194 195 195 - const slug = useTraktAuthStore.getState().user?.ids?.slug; 196 - if (slug) { 197 - try { 198 - const lists = await traktService.getLists(slug); 199 - const currentBookmarks = useBookmarkStore.getState().bookmarks; 200 - let modifiedBookmarks = { ...currentBookmarks }; 196 + // Collections sync disabled - only watchlist is synced, no Trakt lists 197 + // const slug = useTraktAuthStore.getState().user?.ids?.slug; 198 + // if (slug) { 199 + // try { 200 + // const lists = await traktService.getLists(slug); 201 + // const currentBookmarks = useBookmarkStore.getState().bookmarks; 202 + // let modifiedBookmarks = { ...currentBookmarks }; 201 203 202 - for (const list of lists) { 203 - const listTitle = list.name; 204 - const items = await traktService.getListItems(slug, listId(list)); 205 - for (const li of items) { 206 - const media = li.movie || li.show; 207 - if (!media?.ids?.tmdb) continue; 204 + // for (const list of lists) { 205 + // const listTitle = list.name; 206 + // const items = await traktService.getListItems(slug, listId(list)); 207 + // for (const li of items) { 208 + // const media = li.movie || li.show; 209 + // if (!media?.ids?.tmdb) continue; 208 210 209 - const tmdbId = media.ids.tmdb.toString(); 210 - const type = li.movie ? "movie" : "show"; 211 - const bookmark = modifiedBookmarks[tmdbId]; 211 + // const tmdbId = media.ids.tmdb.toString(); 212 + // const type = li.movie ? "movie" : "show"; 213 + // const bookmark = modifiedBookmarks[tmdbId]; 212 214 213 - if (!bookmark) { 214 - const poster = await getPosterForMedia(tmdbId, type); 215 - modifiedBookmarks[tmdbId] = { 216 - type: type as "movie" | "show", 217 - title: media.title, 218 - year: media.year, 219 - poster, 220 - updatedAt: Date.now(), 221 - group: [listTitle], 222 - }; 223 - } else { 224 - const groups = bookmark.group ?? []; 225 - if (!groups.includes(listTitle)) { 226 - const { modifiedBookmarks: next } = modifyBookmarks( 227 - modifiedBookmarks, 228 - [tmdbId], 229 - { addGroups: [listTitle] }, 230 - ); 231 - modifiedBookmarks = next; 232 - } 233 - } 234 - } 235 - } 215 + // if (!bookmark) { 216 + // const poster = await getPosterForMedia(tmdbId, type); 217 + // modifiedBookmarks[tmdbId] = { 218 + // type: type as "movie" | "show", 219 + // title: media.title, 220 + // year: media.year, 221 + // poster, 222 + // updatedAt: Date.now(), 223 + // group: [listTitle], 224 + // }; 225 + // } else { 226 + // const groups = bookmark.group ?? []; 227 + // if (!groups.includes(listTitle)) { 228 + // const { modifiedBookmarks: next } = modifyBookmarks( 229 + // modifiedBookmarks, 230 + // [tmdbId], 231 + // { addGroups: [listTitle] }, 232 + // ); 233 + // modifiedBookmarks = next; 234 + // } 235 + // } 236 + // } 237 + // } 236 238 237 - const hasNewBookmarks = 238 - Object.keys(modifiedBookmarks).length !== 239 - Object.keys(currentBookmarks).length; 240 - const hasGroupChanges = Object.keys(modifiedBookmarks).some( 241 - (id) => 242 - JSON.stringify(modifiedBookmarks[id]?.group ?? []) !== 243 - JSON.stringify(currentBookmarks[id]?.group ?? []), 244 - ); 245 - if (hasNewBookmarks || hasGroupChanges) { 246 - replaceBookmarks(modifiedBookmarks); 247 - } 248 - } catch (listError) { 249 - console.warn("Failed to sync Trakt lists (groups)", listError); 250 - } 251 - } 239 + // const hasNewBookmarks = 240 + // Object.keys(modifiedBookmarks).length !== 241 + // Object.keys(currentBookmarks).length; 242 + // const hasGroupChanges = Object.keys(modifiedBookmarks).some( 243 + // (id) => 244 + // JSON.stringify(modifiedBookmarks[id]?.group ?? []) !== 245 + // JSON.stringify(currentBookmarks[id]?.group ?? []), 246 + // ); 247 + // if (hasNewBookmarks || hasGroupChanges) { 248 + // replaceBookmarks(modifiedBookmarks); 249 + // } 250 + // } catch (listError) { 251 + // console.warn("Failed to sync Trakt lists (groups)", listError); 252 + // } 253 + // } 252 254 } catch (error) { 253 255 console.error("Failed to sync Trakt watchlist to local", error); 254 256 } finally { ··· 257 259 }, [accessToken, replaceBookmarks]); 258 260 259 261 const fullSync = useCallback(async () => { 260 - await syncWatchlistFromTrakt(); // Pull Trakt → local, merge 261 - await syncBookmarksToTrakt(); // Push local → Trakt 262 + // Push local → Trakt first so our changes reach Trakt before we pull 263 + await syncBookmarksToTrakt(); 264 + await syncWatchlistFromTrakt(); // Then pull Trakt → local, merge 262 265 }, [syncWatchlistFromTrakt, syncBookmarksToTrakt]); 263 266 264 267 // Wait for Trakt auth store to rehydrate from persist (accessToken may be null on first render) ··· 281 284 }; 282 285 }, []); 283 286 284 - // On mount (after hydration): pull immediately (Trakt → local) 287 + // On mount (after hydration): full sync (push then pull) 285 288 useEffect(() => { 286 289 if (!hydrated || !accessToken) return; 287 - syncWatchlistFromTrakt(); 288 290 const t = setTimeout(fullSync, INITIAL_SYNC_DELAY_MS); 289 291 return () => clearTimeout(t); 290 - }, [hydrated, accessToken, syncWatchlistFromTrakt, fullSync]); 292 + }, [hydrated, accessToken, fullSync]); 291 293 292 294 // Periodic full sync (pull + push) 293 295 useInterval(fullSync, TRAKT_SYNC_INTERVAL_MS);