Skip to content

Commit d12b72f

Browse files
authoredJan 24, 2025
feat: slur replacement using IndexedDB (#663), download datasets, hover-for-metadata from indexeddb
* chore: basic indexdb setup * fix: database init * chore: small changes * chore: indexing all 3 slur array's * fix: adding source to the db * feat: slur replacment using indexedDB * chore: removing minor logs * refactor: seperate file for main slur list * chore: renaming funtions * feat: slur replacment support for personal slurlist * chore: minor changes * chore: use personal slur list for replacment * fix: personal slur list for slur replacement * fix: right click add slur to personal list * feat: sync with public crowsrouced slurs * fix: slur metadata shown from public table
1 parent c7834bb commit d12b72f

16 files changed

+681
-194
lines changed
 

‎browser-extension/plugin/package-lock.json

+6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎browser-extension/plugin/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
"dependencies": {
4444
"axios": "1.6.2",
4545
"concurrently": "8.2.2",
46+
"dexie": "^4.0.11",
4647
"dom-to-image": "2.6.0",
4748
"dom-to-image-improved": "2.8.0",
4849
"dom-to-image-more": "3.2.0",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import axios from 'axios';
2+
import config from '../config';
3+
4+
const { API_URL } = config;
5+
6+
export async function getPublicSlurs() {
7+
try {
8+
const res = await axios.get(`${API_URL}/api/dataset/slur/1`);
9+
10+
return res.data.slurs;
11+
} catch (error) {
12+
throw error;
13+
}
14+
}
15+
16+
export async function getPublicSlursMetadata() {
17+
try {
18+
const res = await axios.get(`${API_URL}/api/dataset/slurmetadata/1`);
19+
20+
return res.data.slurs_metadata;
21+
} catch (error) {
22+
throw error;
23+
}
24+
}

‎browser-extension/plugin/src/background.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,4 @@ userBrowserContextMenus.onClicked.addListener((info, tab) => {
6565
default:
6666
console('unexpected action');
6767
}
68-
});
68+
});

‎browser-extension/plugin/src/chrome.js

+35-24
Original file line numberDiff line numberDiff line change
@@ -70,34 +70,45 @@ const set = (key, value) => {
7070
});
7171
};
7272

73-
function sendMessage(type) {
74-
if (type == 'updateData') {
75-
userBrowserTabs.query(
76-
{ active: true, currentWindow: true },
77-
function (tabs) {
78-
userBrowserTabs.sendMessage(
79-
tabs[0].id,
80-
{ type: 'updateData' },
81-
function (response) {
82-
console.log(response);
83-
}
84-
);
85-
}
86-
);
87-
}
73+
function sendMessage(type, data = null) {
74+
return new Promise((resolve, reject) => {
75+
const message = { type };
76+
if (data) {
77+
message.data = data;
78+
}
79+
80+
if (
81+
type === 'updateData' ||
82+
type === 'fetchPersonalSlurs' ||
83+
type === 'syncApprovedCrowdsourcedSlurs'
84+
) {
85+
userBrowserTabs.query(
86+
{ active: true, currentWindow: true },
87+
function (tabs) {
88+
userBrowserTabs.sendMessage(
89+
tabs[0].id,
90+
message,
91+
function (response) {
92+
resolve(response);
93+
}
94+
);
95+
}
96+
);
97+
} else {
98+
reject(new Error('Unsupported message type'));
99+
}
100+
});
88101
}
89102

90103
function addListener(type, func, response) {
91-
chrome.runtime.onMessage.addListener(async function (
92-
message,
93-
sender,
94-
sendResponse
95-
) {
96-
if (message.type === type) {
97-
func();
98-
sendResponse(response);
104+
chrome.runtime.onMessage.addListener(
105+
async function (message, sender, sendResponse) {
106+
if (message.type === type) {
107+
func();
108+
sendResponse(response);
109+
}
99110
}
100-
});
111+
);
101112
}
102113

103114
export default {

‎browser-extension/plugin/src/content-script.js

+127-62
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,19 @@ import transform_v2 from './transform-v2';
55
import { log } from './logger';
66
import repository from './repository';
77
const { getUserData, getPreferenceData, setPreferenceData } = repository;
8-
import { updateSlurList } from './slur-replace';
98
import transformGeneral from './transform-general';
109
import Api from './ui-components/pages/Api';
10+
import {
11+
initializeSlurs,
12+
getSlursBySource,
13+
addSlur,
14+
deleteSlur,
15+
slurExists,
16+
bulkAddSlurs,
17+
convertSlurMetadataFromDBtoJSON
18+
} from './slur-store';
1119
import { createCrowdsourceSlur } from './api/crowdsource-slurs';
20+
import { getPublicSlurs } from './api/public-slurs';
1221

1322
const { createSlurAndCategory } = Api;
1423

@@ -79,85 +88,141 @@ function processPage(newUrl) {
7988
* eg : When a user clicks on a tweet on their home timeline, they
8089
* go from the home page to the user status page.
8190
*/
82-
chrome.runtime.onMessage.addListener(async function (request) {
83-
if (request.type === 'updateData') {
84-
console.log('data changed. time to update slurs');
85-
const preference = await getPreferenceData();
86-
console.log(preference);
87-
if (preference.slurList != undefined) {
88-
updateSlurList(preference.slurList);
89-
processPage(location.href);
90-
}
91-
return true;
92-
}
93-
if (request.message === 'URL_CHANGED') {
94-
const newUrl = request.url;
95-
log('Url Changed', newUrl);
96-
processPage(location.href);
97-
return true;
98-
}
99-
if (request.type === 'SLUR_ADDED') {
100-
const slur = request.slur;
101-
log('slur added from bg', slur);
102-
const pref = await getPreferenceData();
103-
let slurList;
104-
105-
const user = await getUserData();
106-
// console.log('USER in content-script', user);
107-
const crowdsourceData = {
108-
label: slur,
109-
};
110-
111-
// Adding Slur to Prefrences
112-
if (!pref || !pref.slurList) {
113-
slurList = slur;
114-
} else {
115-
slurList = pref.slurList;
116-
if (!slurList || slurList === '') {
117-
slurList = slur;
118-
} else {
119-
slurList += `,${slur}`;
91+
chrome.runtime.onMessage.addListener(
92+
async function (request, sender, sendResponse) {
93+
if (request.type === 'updateData') {
94+
try {
95+
const newSlurs = request.data;
96+
console.log('New slurs received:', newSlurs);
97+
// fetch exisiting slurs
98+
const existingSlurs = (await getSlursBySource('personal')).map(
99+
(slur) => slur.word
100+
);
101+
// Add new slurs to the database
102+
for (const slur of newSlurs) {
103+
if (!existingSlurs.includes(slur)) {
104+
await addSlur(slur, 'personal');
105+
}
106+
}
107+
// Remove slurs from the database that no longer exist in the new list
108+
for (const slur of existingSlurs) {
109+
if (!newSlurs.includes(slur)) {
110+
await deleteSlur(slur, 'personal');
111+
}
112+
}
113+
processPage(location.href);
114+
} catch (error) {
115+
console.error('Error during updating slur list:', error);
120116
}
117+
return true;
121118
}
122-
try {
123-
await setPreferenceData({ ...pref, slurList });
124-
} catch (error) {
125-
console.error('error updating pref data', error);
119+
if (request.type === 'fetchPersonalSlurs') {
120+
try {
121+
const personalSlurs = await getSlursBySource('personal');
122+
const slurArr = personalSlurs.map((slur) => slur.word);
123+
console.log('Sending slurs back to pref:', slurArr);
124+
return slurArr;
125+
} catch (error) {
126+
console.error(
127+
'Error fetching personal slurs in content script:',
128+
error
129+
);
130+
// sendResponse({ success: false, error: error.message });
131+
}
126132
}
133+
if (request.type === 'syncApprovedCrowdsourcedSlurs') {
134+
const source = 'public_crowdsourced_slurs';
135+
try {
136+
const publicSlurs = await getPublicSlurs();
137+
const publicSlursArray = publicSlurs.map((slur) => slur.label);
138+
// console.log(publicSlursArray);
127139

128-
//Crowdsourcing Slur
129-
try {
130-
// await createSlurAndCategory(user.accessToken, crowdsourceData);
131-
await createCrowdsourceSlur(crowdsourceData, user.token)
132-
console.log('finsihed POST req');
133-
window.alert(`Slur word "${slur}" added to Uli`);
134-
} catch (error) {
135-
console.log(error);
140+
const filteredSlurs = [];
141+
for (const slur of publicSlursArray) {
142+
const exists = await slurExists(slur, source);
143+
if (!exists) {
144+
filteredSlurs.push(slur);
145+
}
146+
}
147+
// If there are slurs to add, bulk add them to the database
148+
if (filteredSlurs.length > 0) {
149+
await bulkAddSlurs(filteredSlurs, source);
150+
} else {
151+
console.log('No new slurs to add.');
152+
}
153+
} catch (error) {
154+
console.error('Error fetch public crowsrouced slurs');
155+
}
136156
}
157+
if (request.message === 'URL_CHANGED') {
158+
const newUrl = request.url;
159+
log('Url Changed', newUrl);
160+
processPage(location.href);
161+
return true;
162+
}
163+
if (request.type === 'SLUR_ADDED') {
164+
const slur = request.slur;
165+
log('slur added from bg', slur);
166+
let slurList;
137167

138-
return true;
139-
}
168+
const user = await getUserData();
169+
// console.log('USER in content-script', user);
170+
const crowdsourceData = {
171+
label: slur
172+
};
173+
174+
// Adding Slur to IndexedDB
175+
try {
176+
const exists = await slurExists(slur, 'personal');
177+
178+
if (!exists) {
179+
await addSlur(slur, 'personal');
180+
log('Slur added to IndexedDB:', slur);
181+
} else {
182+
log('Slur already exists in IndexedDB, skipping:', slur);
183+
}
184+
} catch (error) {
185+
console.error('Error handling SLUR_ADDED request:', error);
186+
}
187+
188+
//Crowdsourcing Slur
189+
try {
190+
// await createSlurAndCategory(user.accessToken, crowdsourceData);
191+
await createCrowdsourceSlur(crowdsourceData, user.token);
192+
console.log('finsihed POST req');
193+
window.alert(`Slur word "${slur}" added to Uli`);
194+
} catch (error) {
195+
console.log(error);
196+
}
197+
198+
return true;
199+
}
140200

141-
if (request.type === 'ULI_ENABLE_SLUR_REPLACEMENT') {
142-
console.log('Toggle change event received', request.payload);
143-
if (!request.payload) {
144-
clearInterval(mainLoadedChecker);
201+
if (request.type === 'ULI_ENABLE_SLUR_REPLACEMENT') {
202+
console.log('Toggle change event received', request.payload);
203+
if (!request.payload) {
204+
clearInterval(mainLoadedChecker);
205+
}
145206
}
146207
}
147-
});
208+
);
148209

149210
window.addEventListener(
150211
'load',
151212
async () => {
152213
console.log('content loaded');
153214
const pref = await getPreferenceData();
154-
const { enableSlurReplacement , enableSlurMetadata } = pref;
215+
const { enableSlurReplacement, enableSlurMetadata } = pref;
216+
217+
// Initialize Slurs on content load
218+
await initializeSlurs();
219+
155220
if (enableSlurMetadata) {
156221
let body = document.getElementsByTagName('body');
157222
let first_body = body[0];
158-
transformGeneral.processNewlyAddedNodesGeneral2(first_body);
159-
}
160-
else if (enableSlurReplacement) {
223+
const jsonData = await convertSlurMetadataFromDBtoJSON();
224+
transformGeneral.processNewlyAddedNodesGeneral2(first_body, jsonData);
225+
} else if (enableSlurReplacement) {
161226
processPage(location.href);
162227
}
163228
},

0 commit comments

Comments
 (0)
Please sign in to comment.