PageSourceSearch

https://www.mangakakalot.gg/js/comment_db.js?v=1.0.1

js mangakakalot.gg collected 2026-10-05 02:01:27 UTC 6,268 bytes, 188 lines download raw bytes

1
2const CommentDB = {
3    dbName: 'CommentDB',
4    dbVersion: 1,
5    storeNames: {
6        reactions: 'reactions',
7        timestamps: 'timestamps',
8    },
9    db: null,
10
11    async open() {
12        return new Promise((resolve, reject) => {
13            const request = indexedDB.open(this.dbName, this.dbVersion);
14
15            request.onupgradeneeded = (event) => {
16                const db = event.target.result;
17
18                if (!db.objectStoreNames.contains(this.storeNames.reactions)) {
19                    const reactionsStore = db.createObjectStore(this.storeNames.reactions, { keyPath: 'comment_id' });
20                    // Create index on user_id for faster queries
21                    reactionsStore.createIndex('reactor_id', 'reactor_id', { unique: false });
22                }
23
24                if (!db.objectStoreNames.contains('timestamps')) {
25                    db.createObjectStore('timestamps');
26                }
27            };
28
29            request.onsuccess = (event) => {
30                this.db = event.target.result;
31                resolve(this.db);
32            };
33
34            request.onerror = (event) => reject(event.target.error);
35        });
36    },
37
38    async setTimestamp(key) {
39        await this.open();
40        const tx = this.db.transaction(this.storeNames.timestamps, 'readwrite');
41        const store = tx.objectStore(this.storeNames.timestamps);
42        store.put(Date.now(), key);
43    },
44
45    async getTimestamp(key) {
46        await this.open();
47        const tx = this.db.transaction(this.storeNames.timestamps, 'readonly');
48        const store = tx.objectStore(this.storeNames.timestamps);
49        return new Promise((resolve) => {
50            const req = store.get(key);
51            req.onsuccess = () => resolve(req.result || 0);
52            req.onerror = () => resolve(0);
53        });
54    },
55
56    async saveToStore(storeName, items) {
57        await this.open();
58        const tx = this.db.transaction(storeName, 'readwrite');
59        const store = tx.objectStore(storeName);
60        items.forEach(item => store.put(item));
61    },
62
63    async getFromStore(storeName) {
64        await this.open();
65        return new Promise((resolve, reject) => {
66            const tx = this.db.transaction(storeName, 'readonly');
67            const store = tx.objectStore(storeName);
68            const req = store.getAll();
69
70            req.onsuccess = () => resolve(req.result);
71            req.onerror = (e) => reject(e.target.error);
72        });
73    },
74
75    async getReactionsByUserId(userId) {
76        await this.open();
77
78        return new Promise((resolve, reject) => {
79            const tx = this.db.transaction(this.storeNames.reactions, 'readonly');
80            const store = tx.objectStore(this.storeNames.reactions);
81            const index = store.index('reactor_id');
82            const req = index.getAll(userId.toString());
83
84            req.onsuccess = () => resolve(req.result);
85            req.onerror = (e) => reject(e.target.error);
86        });
87    },
88
89    async getReactionByCommentAndUser(commentId, userId) {
90        await this.open();
91
92        return new Promise((resolve, reject) => {
93            const tx = this.db.transaction(this.storeNames.reactions, 'readonly');
94            const store = tx.objectStore(this.storeNames.reactions);
95            const req = store.get(commentId);
96
97            req.onsuccess = () => {
98                const reaction = req.result;
99                if (reaction && reaction.reactor_id === userId) {
100                    resolve(reaction);
101                } else {
102                    resolve(null);
103                }
104            };
105
106            req.onerror = (e) => reject(e.target.error);
107        });
108    },
109
110    async fetchAndCacheMyReactions(userId, apiUrl = '/api/comments/my-reactions') {
111        try {
112            const timeoutMs = 1000 * 60 * 60;
113            const lastFetched = await this.getTimestamp('lastFetchReactions');
114            const now = Date.now();
115
116            if (now - lastFetched < timeoutMs) {
117                return await this.getFromStore(this.storeNames.reactions);
118            }
119
120            const response = await fetch(apiUrl);
121            const { data } = await response.json();
122
123            const reactions = data.reactions || [];
124
125            await this.clearUserReactions(userId);
126
127            await this.saveToStore(this.storeNames.reactions, reactions);
128
129            await this.setTimestamp('lastFetchReactions');
130
131            return reactions;
132        } catch (err) {
133            console.error('Error fetching lastFetchReactions:', err);
134            return [];
135        }
136    },
137
138    async clearUserReactions(userId) {
139        await this.open();
140
141        return new Promise((resolve, reject) => {
142            const tx = this.db.transaction(this.storeNames.reactions, 'readwrite');
143            const store = tx.objectStore(this.storeNames.reactions);
144            const index = store.index('reactor_id');
145            const req = index.getAllKeys(userId);
146
147            req.onsuccess = () => {
148                const commentIds = req.result;
149
150                // Delete all reactions for this user
151                commentIds.forEach(commentId => {
152                    store.delete(commentId);
153                });
154
155                resolve();
156            };
157
158            req.onerror = (e) => reject(e.target.error);
159        });
160    },
161
162    async getReactions(timeoutMs = 1000 * 60 * 60) {
163        const lastFetched = await this.getTimestamp('lastFetchReactions');
164        const now = Date.now();
165
166        if (now - lastFetched < timeoutMs) {
167            return await this.getFromStore(this.storeNames.reactions);
168        }
169
170        return await this.fetchAndCacheMyReactions();
171    },
172
173    async saveReaction(reactionData) {
174        await this.open();
175        const tx = this.db.transaction(this.storeNames.reactions, 'readwrite');
176        const store = tx.objectStore(this.storeNames.reactions);
177        store.put(reactionData); // This handles both create and update
178    },
179
180    async deleteReaction(commentId) {
181        await this.open();
182        const tx = this.db.transaction(this.storeNames.reactions, 'readwrite');
183        const store = tx.objectStore(this.storeNames.reactions);
184        store.delete(commentId);
185    },
186};
187
188window.CommentDB = CommentDB;

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.