xxx777xxxASD commited on
Commit
687f589
·
verified ·
1 Parent(s): 2c90a24

Upload 4 files

Browse files
BetterChub/background.js ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ console.log('Background script loaded');
2
+
3
+ let apiUrl = '';
4
+
5
+ chrome.webRequest.onBeforeSendHeaders.addListener(
6
+ (details) => {
7
+ console.log('Intercepted request:', details.url);
8
+ const apiKeyHeader = details.requestHeaders.find(h => h.name === 'CH-API-KEY');
9
+ if (apiKeyHeader) {
10
+ console.log('API Key found:', apiKeyHeader.value);
11
+ chrome.storage.local.set({ apiKey: apiKeyHeader.value });
12
+ }
13
+ if (details.url.includes('api.chub.ai/search')) {
14
+ console.log('API URL found:', details.url);
15
+ apiUrl = details.url;
16
+ chrome.storage.local.set({ apiUrl: details.url });
17
+ }
18
+ return { requestHeaders: details.requestHeaders };
19
+ },
20
+ { urls: ["https://api.chub.ai/*"] },
21
+ ["requestHeaders"]
22
+ );
BetterChub/content.js ADDED
@@ -0,0 +1,199 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ console.log('Content script loaded');
2
+
3
+ let currentPage = 1;
4
+ let totalPages = 1;
5
+ let apiKey = '';
6
+ let apiUrl = '';
7
+ let lastUrl = '';
8
+
9
+ function createNavigationHTML() {
10
+ return `
11
+ <div class="nav-row">
12
+ <button id="firstPage" class="ant-btn css-s6hibu ant-btn-default"><span>First</span></button>
13
+ <button id="prevPage" class="ant-btn css-s6hibu ant-btn-default"><span>Previous</span></button>
14
+ <span id="pageInfo">Loading...</span>
15
+ <button id="nextPage" class="ant-btn css-s6hibu ant-btn-default"><span>Next</span></button>
16
+ <button id="lastPage" class="ant-btn css-s6hibu ant-btn-default"><span>Last</span></button>
17
+ </div>
18
+ <div class="nav-row">
19
+ <div class="input-group">
20
+ <input type="number" id="pageInput" min="1" max="${totalPages}" value="${currentPage}">
21
+ <button id="goToPage" class="ant-btn css-s6hibu ant-btn-default"><span>Go</span></button>
22
+ </div>
23
+ </div>
24
+ `;
25
+ }
26
+
27
+ function updateNavigation() {
28
+ console.log('Updating navigation');
29
+ const navContainers = document.querySelectorAll('.navigation-container');
30
+ if (navContainers.length === 0) {
31
+ console.error('Navigation containers not found');
32
+ return;
33
+ }
34
+
35
+ navContainers.forEach(container => {
36
+ container.innerHTML = createNavigationHTML();
37
+
38
+ container.querySelector('#firstPage').addEventListener('click', () => changePage(1));
39
+ container.querySelector('#prevPage').addEventListener('click', () => changePage(currentPage - 1));
40
+ container.querySelector('#nextPage').addEventListener('click', () => changePage(currentPage + 1));
41
+ container.querySelector('#lastPage').addEventListener('click', () => changePage(totalPages));
42
+ container.querySelector('#goToPage').addEventListener('click', () => {
43
+ const pageInput = container.querySelector('#pageInput');
44
+ changePage(parseInt(pageInput.value));
45
+ });
46
+ });
47
+
48
+ updatePageInfo();
49
+ console.log('Navigation updated successfully');
50
+ }
51
+
52
+ function updatePageInfo() {
53
+ const pageInfoElements = document.querySelectorAll('#pageInfo');
54
+ pageInfoElements.forEach(element => {
55
+ element.textContent = `Page ${currentPage} of ${totalPages}`;
56
+ });
57
+ }
58
+
59
+ function changePage(newPage) {
60
+ console.log(`Changing page to ${newPage}`);
61
+ if (newPage < 1 || newPage > totalPages) {
62
+ console.warn(`Invalid page number: ${newPage}`);
63
+ return;
64
+ }
65
+ currentPage = newPage;
66
+ updateNavigation();
67
+ // Update URL and trigger page reload
68
+ const url = new URL(window.location.href);
69
+ url.searchParams.set('page', currentPage);
70
+ console.log(`Navigating to: ${url.toString()}`);
71
+ window.location.href = url.toString();
72
+ }
73
+
74
+ async function findTotalPages() {
75
+ console.log('Finding total pages');
76
+ let left = 1;
77
+ let right = 1000; // Assuming a reasonable upper limit
78
+
79
+ while (left <= right) {
80
+ const mid = Math.floor((left + right) / 2);
81
+ console.log(`Checking page ${mid}`);
82
+ const hasContent = await checkPageContent(mid);
83
+
84
+ if (hasContent) {
85
+ left = mid + 1;
86
+ } else {
87
+ right = mid - 1;
88
+ }
89
+ }
90
+
91
+ console.log(`Total pages found: ${right}`);
92
+ return right; // This will be the last page with content
93
+ }
94
+
95
+ async function checkPageContent(page) {
96
+ const url = new URL(apiUrl);
97
+ url.searchParams.set('page', page);
98
+
99
+ console.log(`Checking content for page ${page}`);
100
+ try {
101
+ const response = await fetch(url.toString(), {
102
+ headers: { 'CH-API-KEY': apiKey }
103
+ });
104
+ const data = await response.json();
105
+ console.log(`Page ${page} content:`, data);
106
+ return data.data.nodes.length > 0;
107
+ } catch (error) {
108
+ console.error(`Error checking page ${page}:`, error);
109
+ return false;
110
+ }
111
+ }
112
+
113
+ async function initializeNavigation() {
114
+ console.log('Initializing navigation');
115
+ currentPage = parseInt(new URL(window.location.href).searchParams.get('page') || '1');
116
+ console.log(`Current page: ${currentPage}`);
117
+ totalPages = await findTotalPages();
118
+ updateNavigation();
119
+ }
120
+
121
+ function waitForApiInfo() {
122
+ chrome.storage.local.get(['apiKey', 'apiUrl'], async (result) => {
123
+ console.log('Retrieved from storage:', result);
124
+ if (result.apiKey && result.apiUrl) {
125
+ apiKey = result.apiKey;
126
+ apiUrl = result.apiUrl;
127
+ console.log('API Key and URL found, initializing navigation');
128
+ await initializeNavigation();
129
+ } else {
130
+ console.log('API Key or URL missing, retrying in 1 second');
131
+ setTimeout(waitForApiInfo, 1000);
132
+ }
133
+ });
134
+ }
135
+
136
+ function addNavigationContainers() {
137
+ const containerDiv = document.querySelector('.mt-2');
138
+ if (containerDiv) {
139
+ // Remove any existing navigation containers
140
+ containerDiv.querySelectorAll('.navigation-container').forEach(el => el.remove());
141
+
142
+ // Add top navigation
143
+ const topNav = document.createElement('div');
144
+ topNav.className = 'navigation-container top-nav';
145
+ topNav.innerHTML = createNavigationHTML();
146
+ containerDiv.insertBefore(topNav, containerDiv.firstChild);
147
+
148
+ // Replace bottom navigation
149
+ const bottomNav = containerDiv.querySelector('.flex.justify-between.mt-4');
150
+ if (bottomNav) {
151
+ bottomNav.className = 'navigation-container bottom-nav';
152
+ bottomNav.innerHTML = createNavigationHTML();
153
+ } else {
154
+ const newBottomNav = document.createElement('div');
155
+ newBottomNav.className = 'navigation-container bottom-nav';
156
+ newBottomNav.innerHTML = createNavigationHTML();
157
+ containerDiv.appendChild(newBottomNav);
158
+ }
159
+
160
+ updateNavigation();
161
+ } else {
162
+ console.error('Container div not found');
163
+ }
164
+ }
165
+
166
+ function checkUrlChange() {
167
+ const currentUrl = window.location.href;
168
+ if (currentUrl !== lastUrl) {
169
+ console.log('URL changed, reinitializing navigation');
170
+ lastUrl = currentUrl;
171
+ waitForApiInfo();
172
+ }
173
+ }
174
+
175
+ // Start the process once the page is fully loaded
176
+ window.addEventListener('load', () => {
177
+ console.log('Page fully loaded, starting navigation enhancement');
178
+ lastUrl = window.location.href;
179
+ addNavigationContainers();
180
+ waitForApiInfo();
181
+ });
182
+
183
+ // Check for URL changes
184
+ setInterval(checkUrlChange, 1000);
185
+
186
+ // Observe DOM changes to add navigation containers when the character list is loaded
187
+ const observer = new MutationObserver((mutations) => {
188
+ for (const mutation of mutations) {
189
+ if (mutation.type === 'childList' && document.querySelector('.mt-2')) {
190
+ console.log('Character list container found, adding navigation containers');
191
+ addNavigationContainers();
192
+ observer.disconnect(); // Stop observing once we've added the navigation containers
193
+ }
194
+ }
195
+ });
196
+
197
+ observer.observe(document.body, { childList: true, subtree: true });
198
+
199
+ console.log('Content script finished loading');
BetterChub/manifest.json ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "manifest_version": 3,
3
+ "name": "BetterChub",
4
+ "version": "1.0",
5
+ "description": "Navigation does *tap* *tap*",
6
+ "permissions": ["webRequest", "storage"],
7
+ "host_permissions": ["https://chub.ai/*", "https://api.chub.ai/*"],
8
+ "background": {
9
+ "service_worker": "background.js"
10
+ },
11
+ "content_scripts": [
12
+ {
13
+ "matches": ["https://chub.ai/*"],
14
+ "js": ["content.js"],
15
+ "css": ["styles.css"]
16
+ }
17
+ ]
18
+ }
BetterChub/styles.css ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .navigation-container {
2
+ display: flex;
3
+ flex-direction: column;
4
+ align-items: center;
5
+ margin-top: 1rem;
6
+ margin-bottom: 1rem;
7
+ }
8
+
9
+ .nav-row {
10
+ display: flex;
11
+ justify-content: center;
12
+ align-items: center;
13
+ margin: 0.5rem 0;
14
+ }
15
+
16
+ #pageInfo {
17
+ margin: 0 1rem;
18
+ font-weight: bold;
19
+ }
20
+
21
+ .input-group {
22
+ display: flex;
23
+ justify-content: center;
24
+ align-items: center;
25
+ }
26
+
27
+ #pageInput {
28
+ width: 50px;
29
+ margin-right: 0.5rem;
30
+ }
31
+
32
+ .top-nav {
33
+ margin-bottom: 1rem;
34
+ }
35
+
36
+ .bottom-nav {
37
+ margin-top: 1rem;
38
+ }