PageSourceSearch

https://www.twitch-clips-storage.com/app/directory_streamer_game/assets/js/favorites_streamer_game.js

js twitch-clips-storage.com collected 2026-10-02 01:47:21 UTC 5,280 bytes, 164 lines download raw bytes

1(() => {
2    "use strict";
3
4    const FAVORITE_STREAMERS_KEY = "favorite_streamers_v1";
5    const FAVORITE_GAMES_KEY = "favorite_games_v1";
6    const ID_LIMIT = 3000;
7
8    function safeParse(jsonText, fallback) {
9        if (!jsonText) {
10            return fallback;
11        }
12        try {
13            return JSON.parse(jsonText);
14        } catch (error) {
15            console.warn("favorite parse error", error);
16            return fallback;
17        }
18    }
19
20    function safeString(value) {
21        if (value === null || value === undefined) {
22            return "";
23        }
24        return String(value).trim();
25    }
26
27    function normalizeId(value) {
28        const id = safeString(value);
29        if (!id) {
30            return "";
31        }
32        return id.slice(0, 128);
33    }
34
35    function sanitizeMap(rawMap, normalizer) {
36        const result = {};
37        if (!rawMap || typeof rawMap !== "object") {
38            return result;
39        }
40
41        Object.keys(rawMap).forEach((rawKey) => {
42            const normalized = normalizer(rawMap[rawKey]);
43            if (!normalized.id) {
44                return;
45            }
46            result[normalized.id] = normalized;
47        });
48
49        return result;
50    }
51
52    function normalizeStreamer(entry) {
53        const id = normalizeId(entry && entry.id);
54        const displayName = safeString(entry && entry.display_name).slice(0, 200);
55        const login = safeString(entry && entry.login).slice(0, 200);
56        return {
57            id,
58            display_name: displayName,
59            login
60        };
61    }
62
63    function normalizeGame(entry) {
64        const id = normalizeId(entry && entry.id);
65        const name = safeString(entry && entry.name).slice(0, 200);
66        return {
67            id,
68            name
69        };
70    }
71
72    function readMap(storageKey, normalizer) {
73        const parsed = safeParse(localStorage.getItem(storageKey), {});
74        const map = sanitizeMap(parsed, normalizer);
75        return map;
76    }
77
78    function writeMap(storageKey, map) {
79        localStorage.setItem(storageKey, JSON.stringify(map));
80    }
81
82    function mapToList(map) {
83        return Object.values(map);
84    }
85
86    function mapKeysLimited(map) {
87        return Object.keys(map).slice(0, ID_LIMIT);
88    }
89
90    function upsert(storageKey, entry, normalizer) {
91        const normalized = normalizer(entry);
92        if (!normalized.id) {
93            return false;
94        }
95        const map = readMap(storageKey, normalizer);
96        map[normalized.id] = normalized;
97        writeMap(storageKey, map);
98        return true;
99    }
100
101    function remove(storageKey, id, normalizer) {
102        const normalizedId = normalizeId(id);
103        if (!normalizedId) {
104            return false;
105        }
106        const map = readMap(storageKey, normalizer);
107        if (!Object.prototype.hasOwnProperty.call(map, normalizedId)) {
108            return false;
109        }
110        delete map[normalizedId];
111        writeMap(storageKey, map);
112        return true;
113    }
114
115    function has(storageKey, id, normalizer) {
116        const normalizedId = normalizeId(id);
117        if (!normalizedId) {
118            return false;
119        }
120        const map = readMap(storageKey, normalizer);
121        return Object.prototype.hasOwnProperty.call(map, normalizedId);
122    }
123
124    function toggle(storageKey, entry, normalizer) {
125        const normalized = normalizer(entry);
126        if (!normalized.id) {
127            return false;
128        }
129        const map = readMap(storageKey, normalizer);
130        const isFavorite = Object.prototype.hasOwnProperty.call(map, normalized.id);
131        if (isFavorite) {
132            delete map[normalized.id];
133        } else {
134            map[normalized.id] = normalized;
135        }
136        writeMap(storageKey, map);
137        return !isFavorite;
138    }
139
140    function clear(storageKey) {
141        localStorage.removeItem(storageKey);
142    }
143
144    window.FavoriteStore = {
145        FAVORITE_STREAMERS_KEY,
146        FAVORITE_GAMES_KEY,
147        getStreamerMap: () => readMap(FAVORITE_STREAMERS_KEY, normalizeStreamer),
148        getGameMap: () => readMap(FAVORITE_GAMES_KEY, normalizeGame),
149        getStreamers: () => mapToList(readMap(FAVORITE_STREAMERS_KEY, normalizeStreamer)),
150        getGames: () => mapToList(readMap(FAVORITE_GAMES_KEY, normalizeGame)),
151        getStreamerIds: () => mapKeysLimited(readMap(FAVORITE_STREAMERS_KEY, normalizeStreamer)),
152        getGameIds: () => mapKeysLimited(readMap(FAVORITE_GAMES_KEY, normalizeGame)),
153        hasStreamer: (id) => has(FAVORITE_STREAMERS_KEY, id, normalizeStreamer),
154        hasGame: (id) => has(FAVORITE_GAMES_KEY, id, normalizeGame),
155        addStreamer: (entry) => upsert(FAVORITE_STREAMERS_KEY, entry, normalizeStreamer),
156        addGame: (entry) => upsert(FAVORITE_GAMES_KEY, entry, normalizeGame),
157        removeStreamer: (id) => remove(FAVORITE_STREAMERS_KEY, id, normalizeStreamer),
158        removeGame: (id) => remove(FAVORITE_GAMES_KEY, id, normalizeGame),
159        toggleStreamer: (entry) => toggle(FAVORITE_STREAMERS_KEY, entry, normalizeStreamer),
160        toggleGame: (entry) => toggle(FAVORITE_GAMES_KEY, entry, normalizeGame),
161        clearStreamers: () => clear(FAVORITE_STREAMERS_KEY),
162        clearGames: () => clear(FAVORITE_GAMES_KEY)
163    };
164})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.