Fix more type errors, refactor a few things

This commit is contained in:
shinigami-eyes 2019-06-29 19:47:05 +02:00
parent db717cfe15
commit da80996a8c
5 changed files with 263 additions and 283 deletions

View File

@ -3,7 +3,7 @@
const PENDING_SUBMISSIONS = ':PENDING_SUBMISSIONS'
const MIGRATION = ':MIGRATION'
const CURRENT_VERSION = 100018;
const CURRENT_VERSION = 100019;
// If a user labels one of these URLs, they're making a mistake. Ignore the label.
// This list includes:
@ -11,7 +11,7 @@ const CURRENT_VERSION = 100018;
// * System pages of supported social networks
// * Archival and link shortening sites.
// * Reddit bots.
var badIdentifiersArray = [
const badIdentifiersArray = [
'archive.is',
'archive.org',
'assets.tumblr.com',
@ -232,12 +232,12 @@ var badIdentifiersArray = [
'youtube.com/redirect',
'youtube.com/watch',
];
var badIdentifiers : {[id: string]: true} = {};
const badIdentifiers : {[id: string]: true} = {};
badIdentifiersArray.forEach(x => badIdentifiers[x] = true);
var lastSubmissionError = null;
var lastSubmissionError : string = null;
var needsInfiniteResubmissionWorkaround = [
const needsInfiniteResubmissionWorkaround = [
'046775268347','094745034139','059025030493','016970595453','016488055088','028573603939',
'047702135398','035965787127','069722626647','044482561296','068530257405','071378971311',
'050784255720','074169481269','001621982155','014636303566','016313013148','051923868290',
@ -246,10 +246,10 @@ var needsInfiniteResubmissionWorkaround = [
'040689448048','048816243838','018152001078','059285890303','073205501344','096068619182'
]
var overrides = null;
var overrides : LabelMap = null;
var accepted = false;
var installationId = null;
var installationId : string = null;
browser.storage.local.get(['overrides', 'accepted', 'installationId'], v => {
if (!v.installationId) {
@ -262,17 +262,17 @@ browser.storage.local.get(['overrides', 'accepted', 'installationId'], v => {
accepted = v.accepted
overrides = v.overrides || {}
var migration = overrides[MIGRATION] || 0;
const migration = overrides[MIGRATION] || 0;
if (migration < CURRENT_VERSION){
for(var key of Object.getOwnPropertyNames(overrides)){
for (const key of Object.getOwnPropertyNames(overrides)){
if (key.startsWith(':')) continue;
if (key.startsWith('facebook.com/a.')){
delete overrides[key];
continue;
}
if (key != key.toLowerCase()){
var v = overrides[key];
let v = overrides[key];
delete overrides[key];
overrides[key.toLowerCase()] = v;
}
@ -281,30 +281,29 @@ browser.storage.local.get(['overrides', 'accepted', 'installationId'], v => {
badIdentifiersArray.forEach(x => delete overrides[x]);
if (needsInfiniteResubmissionWorkaround.indexOf(installationId.substring(0, 12)) != -1)
overrides[PENDING_SUBMISSIONS] = [];
overrides[MIGRATION] = CURRENT_VERSION;
overrides[PENDING_SUBMISSIONS] = <any>[];
overrides[MIGRATION] = <any>CURRENT_VERSION;
browser.storage.local.set({ overrides: overrides });
}
})
const bloomFilters : BloomFilter[] = [];
function loadBloomFilter(name: string) {
async function loadBloomFilter(name: LabelKind) {
var url = browser.extension.getURL('data/' + name + '.dat');
fetch(url).then(response => {
response.arrayBuffer().then(arrayBuffer => {
var array = new Uint32Array(arrayBuffer);
var b = new BloomFilter(array, 20);
const url = browser.extension.getURL('data/' + name + '.dat');
const response = await fetch(url);
const arrayBuffer = await response.arrayBuffer();
const array = new Uint32Array(arrayBuffer);
const b = new BloomFilter(array, 20);
b.name = name;
bloomFilters.push(b);
});
});
}
browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
browser.runtime.onMessage.addListener<ShinigamiEyesMessage, ShinigamiEyesMessage | LabelMap>((message, sender, sendResponse) => {
if (message.acceptClicked !== undefined) {
accepted = message.acceptClicked;
browser.storage.local.set({ accepted: accepted });
@ -314,22 +313,22 @@ browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
uncommittedResponse = null;
return;
}
var response = {};
var transphobic = message.myself && bloomFilters.filter(x => x.name == 'transphobic')[0].test(message.myself);
for (var id of message.ids) {
const response : LabelMap = {};
const transphobic = message.myself && bloomFilters.filter(x => x.name == 'transphobic')[0].test(message.myself);
for (const id of message.ids) {
if (overrides[id] !== undefined) {
response[id] = overrides[id];
continue;
}
if (transphobic) {
if (id == message.myself) continue;
var sum = 0;
for (var i = 0; i < id.length; i++) {
let sum = 0;
for (let i = 0; i < id.length; i++) {
sum += id.charCodeAt(i);
}
if (sum % 8 != 0) continue;
}
for (var bloomFilter of bloomFilters) {
for (const bloomFilter of bloomFilters) {
if (bloomFilter.test(id)) response[id] = bloomFilter.name;
}
}
@ -368,11 +367,11 @@ createContextMenu('Mark as t-friendly', 'mark-t-friendly');
createContextMenu('Clear', 'mark-none');
createContextMenu('Help', 'help');
var uncommittedResponse = null;
var uncommittedResponse : ShinigamiEyesSubmission = null;
async function submitPendingRatings() {
var submitted = overrides[PENDING_SUBMISSIONS].map(x => x);
var requestBody = {
const submitted = getPendingSubmissions().map(x => x);
const requestBody = {
installationId: installationId,
lastError: lastSubmissionError,
entries: submitted
@ -380,17 +379,17 @@ async function submitPendingRatings() {
lastSubmissionError = null;
console.log('Sending request');
try {
var response = await fetch('https://k5kk18774h.execute-api.us-east-1.amazonaws.com/default/shinigamiEyesSubmission', {
const response = await fetch('https://k5kk18774h.execute-api.us-east-1.amazonaws.com/default/shinigamiEyesSubmission', {
body: JSON.stringify(requestBody),
method: 'POST',
credentials: 'omit',
});
if (response.status != 200) throw ('HTTP status: ' + response.status)
var result = await response.text();
const result = await response.text();
if (result != 'SUCCESS') throw 'Bad response: ' + ('' + result).substring(0, 20);
overrides[PENDING_SUBMISSIONS] = overrides[PENDING_SUBMISSIONS].filter(x => submitted.indexOf(x) == -1);
overrides[PENDING_SUBMISSIONS] = <any>getPendingSubmissions().filter(x => submitted.indexOf(x) == -1);
browser.storage.local.set({ overrides: overrides });
} catch(e) {
lastSubmissionError = '' + e
@ -398,12 +397,16 @@ async function submitPendingRatings() {
}
function getPendingSubmissions() : ShinigamiEyesSubmission[]{
return <any>overrides[PENDING_SUBMISSIONS];
}
function saveLabel(response) {
function saveLabel(response: ShinigamiEyesSubmission) {
if (accepted) {
if (!overrides[PENDING_SUBMISSIONS]) {
overrides[PENDING_SUBMISSIONS] = Object.getOwnPropertyNames(overrides)
.map(x => { return { identifier: x, label: overrides[x] } });
if (!getPendingSubmissions()) {
overrides[PENDING_SUBMISSIONS] = <any>Object.getOwnPropertyNames(overrides)
.map<ShinigamiEyesSubmission>(x => { return { identifier: x, label: overrides[x] } });
}
overrides[response.identifier] = response.mark;
if (response.secondaryIdentifier)
@ -411,7 +414,7 @@ function saveLabel(response) {
browser.storage.local.set({ overrides: overrides });
response.version = CURRENT_VERSION;
response.submissionId = (Math.random() + '').replace('.', '');
overrides[PENDING_SUBMISSIONS].push(response);
getPendingSubmissions().push(response);
submitPendingRatings();
//console.log(response);
browser.tabs.sendMessage(response.tabId, { updateAllLabels: true });
@ -436,18 +439,18 @@ browser.contextMenus.onClicked.addListener(function (info, tab) {
return;
}
var tabId = tab.id;
var frameId = info.frameId;
const tabId = tab.id;
const frameId = info.frameId;
var label = <LabelKind>info.menuItemId.substring('mark-'.length);
if (label == 'none') label = '';
browser.tabs.sendMessage<ShinigamiSubmission, ShinigamiSubmission>(tabId, {
browser.tabs.sendMessage<ShinigamiEyesSubmission, ShinigamiEyesSubmission>(tabId, {
mark: label,
url: info.linkUrl,
tabId: tabId,
frameId: frameId,
// elementId: info.targetElementId,
debug: overrides.debug
debug: <any>overrides.debug
}, { frameId: frameId }, response => {
if (!response.identifier) return;
if (response.mark){

View File

@ -8,30 +8,14 @@ if (hostname.endsWith('.reddit.com')) hostname = 'reddit.com';
if (hostname.endsWith('.facebook.com')) hostname = 'facebook.com';
if (hostname.endsWith('.youtube.com')) hostname = 'youtube.com';
var myself = null;
var myself : string = null;
function fixupSiteStyles() {
if (hostname == 'reddit.com') {
myself = document.querySelector('#header-bottom-right .user a');
if (!myself) {
var m : any = document.querySelector('#USER_DROPDOWN_ID');
if (m) {
m = [...m.querySelectorAll('*')].filter(x => x.childNodes.length == 1 && x.firstChild.nodeType == 3).map(x => x.textContent)[0]
if (m) myself = 'reddit.com/user/' + m;
}
}
}
if (hostname == 'facebook.com') {
var m : any = document.querySelector("[id^='profile_pic_header_']")
let m = document.querySelector("[id^='profile_pic_header_']")
if (m) myself = 'facebook.com/' + captureRegex(m.id, /header_(\d+)/);
}
if (hostname == 'medium.com') {
var style = document.createElement('style');
style.textContent = `
} else if (hostname == 'medium.com') {
addStyleSheet(`
a.show-thread-link, a.ThreadedConversation-moreRepliesLink {
color: inherit !important;
}
@ -39,34 +23,20 @@ function fixupSiteStyles() {
.stream-item a:hover .fullname,
.stream-item a:active .fullname
{color:inherit;}
`;
document.head.appendChild(style);
}
if (isHostedOn(hostname, 'tumblr.com')) {
var style = document.createElement('style');
style.textContent = `
`);
} else if (domainIs(hostname, 'tumblr.com')) {
addStyleSheet(`
.assigned-label-transphobic { outline: 2px solid #991515 !important; }
.assigned-label-t-friendly { outline: 1px solid #77B91E !important; }
`;
document.head.appendChild(style);
}
if(hostname.indexOf('wiki') != -1){
var style = document.createElement('style');
style.textContent = `
`);
} else if (hostname.indexOf('wiki') != -1){
addStyleSheet(`
.assigned-label-transphobic { outline: 1px solid #991515 !important; }
.assigned-label-t-friendly { outline: 1px solid #77B91E !important; }
`;
document.head.appendChild(style);
}
if (hostname == 'twitter.com') {
myself = document.querySelector('.DashUserDropdown-userInfo a');
var style = document.createElement('style');
style.textContent = `
`);
} else if (hostname == 'twitter.com') {
myself = getIdentifier(<HTMLAnchorElement>document.querySelector('.DashUserDropdown-userInfo a'));
addStyleSheet(`
.pretty-link b, .pretty-link s {
color: inherit !important;
}
@ -78,43 +48,48 @@ function fixupSiteStyles() {
.stream-item a:hover .fullname,
.stream-item a:active .fullname
{color:inherit;}
`;
document.head.appendChild(style);
`);
} else if (hostname == 'reddit.com') {
var style = document.createElement('style');
style.textContent = `
.author { color: #369 !important;}
`;
document.head.appendChild(style);
myself = getIdentifier(<HTMLAnchorElement>document.querySelector('#header-bottom-right .user a'));
if (!myself) {
let m = document.querySelector('#USER_DROPDOWN_ID');
if (m) {
let username = [...m.querySelectorAll('*')].filter(x => x.childNodes.length == 1 && x.firstChild.nodeType == 3).map(x => x.textContent)[0]
if (username) myself = 'reddit.com/user/' + username;
}
}
addStyleSheet(`
.author { color: #369 !important;}
`);
}
}
function addStyleSheet(css: string){
const style = document.createElement('style');
style.textContent = css;
document.head.appendChild(style);
}
function maybeDisableCustomCss() {
var shouldDisable = null;
var shouldDisable: (s: {ownerNode: HTMLElement}) => boolean = null;
if (hostname == 'twitter.com') shouldDisable = x => x.ownerNode && x.ownerNode.id && x.ownerNode.id.startsWith('user-style');
else if (hostname == 'medium.com') shouldDisable = x => x.ownerNode && x.ownerNode.className && x.ownerNode.className == 'js-collectionStyle';
else if (hostname == 'disqus.com') shouldDisable = x => x.ownerNode && x.ownerNode.id && x.ownerNode.id.startsWith('css_');
if (shouldDisable)
[...document.styleSheets].filter(shouldDisable).forEach(x => x.disabled = true);
[...document.styleSheets].filter(<any>shouldDisable).forEach(x => x.disabled = true);
}
function init() {
fixupSiteStyles();
if (isHostedOn(hostname, 'youtube.com')) {
if (domainIs(hostname, 'youtube.com')) {
setInterval(updateYouTubeChannelHeader, 300);
setInterval(updateAllLabels, 6000);
}
if (myself && (myself.href || myself.startsWith('http:') || myself.startsWith('https:')))
myself = getIdentifier(myself);
console.log('Self: ' + myself)
maybeDisableCustomCss();
updateAllLabels();
@ -135,7 +110,6 @@ function init() {
}
}
solvePendingLabels();
});
observer.observe(document.body, {
@ -143,15 +117,14 @@ function init() {
subtree: true
});
document.addEventListener('contextmenu', evt => {
lastRightClickedElement = evt.target;
lastRightClickedElement = <HTMLElement>evt.target;
}, true);
}
var lastRightClickedElement = null;
var lastAppliedYouTubeUrl = null;
var lastAppliedYouTubeTitle = null;
var lastRightClickedElement : HTMLElement = null;
var lastAppliedYouTubeUrl : string = null;
var lastAppliedYouTubeTitle : string = null;
function updateYouTubeChannelHeader() {
var url = window.location.href;
@ -187,24 +160,21 @@ function updateYouTubeChannelHeader() {
function updateAllLabels(refresh?: boolean) {
if (refresh) knownLabels = {};
var links = document.links;
for (var i = 0; i < links.length; i++) {
var a = <HTMLAnchorElement>links[i];
for (const a of document.getElementsByTagName('a')) {
initLink(a);
}
solvePendingLabels();
}
var knownLabels: LabelMap = {};
var knownLabels = {};
var labelsToSolve = [];
var labelsToSolve : LabelToSolve[] = [];
function solvePendingLabels() {
if (!labelsToSolve.length) return;
var uniqueIdentifiers = Array.from(new Set(labelsToSolve.map(x => x.identifier)));
var tosolve = labelsToSolve;
labelsToSolve = [];
browser.runtime.sendMessage({ ids: uniqueIdentifiers, myself: myself }, response => {
browser.runtime.sendMessage<ShinigamiEyesCommand, LabelMap>({ ids: uniqueIdentifiers, myself: <string>myself }, (response: LabelMap) => {
for (const item of tosolve) {
var label = response[item.identifier];
knownLabels[item.identifier] = label || '';
@ -213,8 +183,7 @@ function solvePendingLabels() {
});
}
function applyLabel(a, identifier) {
function applyLabel(a: HTMLAnchorElement, identifier: string) {
if (a.assignedCssLabel) {
a.classList.remove('assigned-label-' + a.assignedCssLabel);
a.classList.remove('has-assigned-label');
@ -246,38 +215,26 @@ function initLink(a: HTMLAnchorElement) {
applyLabel(a, identifier);
}
function isHostedOn(/** @type {string}*/fullHost, /** @type {string}*/baseHost) {
if (baseHost.length > fullHost.length) return false;
if (baseHost.length == fullHost.length) return baseHost == fullHost;
var k = fullHost.charCodeAt(fullHost.length - baseHost.length - 1);
if (k == 0x2E) return fullHost.endsWith(baseHost);
function domainIs(host: string, baseDomain: string) {
if (baseDomain.length > host.length) return false;
if (baseDomain.length == host.length) return baseDomain == host;
var k = host.charCodeAt(host.length - baseDomain.length - 1);
if (k == 0x2E /* . */) return host.endsWith(baseDomain);
else return false;
}
function getQuery(search: string) : any {
if (!search) return {};
var s = {};
if (search.startsWith('?')) search = search.substring(1);
for (var pair of search.split('&')) {
var z = pair.split('=');
if (z.length != 2) continue;
s[decodeURIComponent(z[0]).replace(/\+/g, ' ')] = decodeURIComponent(z[1].replace(/\+/g, ' '));
}
return s;
}
function takeFirstPathComponents(path: string, num: number) {
function getPartialPath(path: string, num: number) {
var m = path.split('/')
m = m.slice(1, 1 + num);
if (m.length && !m[m.length - 1]) m.length--;
if (m.length != num) return '!!'
return '/' + m.join('/');
}
function takeNthPathComponent(path: string, nth: number) {
return path.split('/')[nth + 1] || null;
function getPathPart(path: string, index: number) {
return path.split('/')[index + 1] || null;
}
function captureRegex(str, regex) {
function captureRegex(str: string, regex: RegExp) {
if (!str) return null;
var match = str.match(regex);
if (match && match[1]) return match[1];
@ -307,30 +264,29 @@ function getCurrentFacebookPageId() {
return null;
}
function getIdentifier(urlstr) {
function getIdentifier(link: string | HTMLAnchorElement) {
try {
var k = getIdentifierInternal(urlstr);
var k = link instanceof Node ? getIdentifierFromElementImpl(link) : getIdentifierFromURLImpl(tryParseURL(link));
if (!k || k.indexOf('!') != -1) return null;
return k.toLowerCase();
} catch (e) {
console.warn("Unable to get identifier for " + urlstr);
console.warn("Unable to get identifier for " + link);
return null;
}
}
function getIdentifierInternal(urlstr) {
if (!urlstr) return null;
function getIdentifierFromElementImpl(element: HTMLAnchorElement): string {
if (!element) return null;
const dataset = element.dataset;
if (hostname == 'reddit.com') {
const parent = urlstr.parentElement;
if (parent && parent.classList.contains('domain') && urlstr.textContent.startsWith('self.')) return null;
}
if (hostname == 'disqus.com') {
if (urlstr.classList && urlstr.classList.contains('time-ago')) return null;
}
if (hostname == 'facebook.com' && urlstr.tagName) {
const parent = urlstr.parentElement;
const parent = element.parentElement;
if (parent && parent.classList.contains('domain') && element.textContent.startsWith('self.')) return null;
} else if (hostname == 'disqus.com') {
if (element.classList && element.classList.contains('time-ago')) return null;
} else if (hostname == 'facebook.com') {
const parent = element.parentElement;
if (parent && (parent.tagName == 'H1' || parent.id == 'fb-timeline-cover-name')) {
const id = getCurrentFacebookPageId();
//console.log('Current fb page: ' + id)
@ -339,17 +295,17 @@ function getIdentifierInternal(urlstr) {
}
// comment timestamp
if (urlstr.firstChild && urlstr.firstChild.tagName == 'ABBR' && urlstr.lastChild == urlstr.firstChild) return null;
if (element.firstChild && (<HTMLElement>element.firstChild).tagName == 'ABBR' && element.lastChild == element.firstChild) return null;
// post 'see more'
if (urlstr.classList.contains('see_more_link')) return null;
if (element.classList.contains('see_more_link')) return null;
// post 'continue reading'
if (parent && parent.classList.contains('text_exposed_link')) return null;
if (urlstr.dataset) {
const hovercard = urlstr.dataset.hovercard;
if (dataset) {
const hovercard = dataset.hovercard;
if (hovercard) {
const id = captureRegex(hovercard, /id=(\d+)/);
if (id)
@ -357,18 +313,18 @@ function getIdentifierInternal(urlstr) {
}
// post Comments link
if (urlstr.dataset.testid == 'UFI2CommentsCount/root') return null;
if (dataset.testid == 'UFI2CommentsCount/root') return null;
// post Comments link
if (urlstr.dataset.commentPreludeRef) return null;
if (dataset.commentPreludeRef) return null;
// page left sidebar
if (urlstr.dataset.endpoint) return null;
if (dataset.endpoint) return null;
// profile tabs
if (urlstr.dataset.tabKey) return null;
if (dataset.tabKey) return null;
const gt = urlstr.dataset.gt;
const gt = dataset.gt;
if (gt) {
const gtParsed = JSON.parse(gt);
if (gtParsed.engagement && gtParsed.engagement.eng_tid) {
@ -377,9 +333,9 @@ function getIdentifierInternal(urlstr) {
}
// comment interaction buttons
if (urlstr.dataset.sigil) return null;
if (dataset.sigil) return null;
let p = <HTMLElement>urlstr;
let p = <HTMLElement>element;
while (p) {
const bt = p.dataset.bt;
if (bt) {
@ -390,109 +346,98 @@ function getIdentifierInternal(urlstr) {
}
}
}
if (urlstr.dataset && urlstr.dataset.expandedUrl) urlstr = urlstr.dataset.expandedUrl;
if (urlstr.href !== undefined) urlstr = urlstr.href;
if (dataset && dataset.expandedUrl) return getIdentifierFromURLImpl(tryParseURL(dataset.expandedUrl));
const href = element.href;
if(href && !href.endsWith('#')) return getIdentifierFromURLImpl(tryParseURL(href));
return null;
}
function tryParseURL(urlstr: string){
if (!urlstr) return null;
if (urlstr.endsWith('#')) return null;
let url;
try {
url = new URL(urlstr);
const url = new URL(urlstr);
if (url.protocol != 'http:' && url.protocol != 'https:') return null;
return url;
} catch(e) {
return null;
}
if (url.protocol != 'http:' && url.protocol != 'https:') return null;
}
function getIdentifierFromURLImpl(url: URL): string{
if(!url) return null;
// nested urls
if (url.href.indexOf('http', 1) != -1) {
if (url.pathname.startsWith('/intl/')) return null; // facebook language switch links
// const values = url.searchParams.values()
// HACK: values(...) is not iterable on facebook (babel polyfill?)
const values = url.search.split('&').map(x => {
const eq = x.indexOf('=');
return eq == -1 ? '' : decodeURIComponent(x.substr(eq + 1));
});
for (const value of values) {
if (value.startsWith('http:') || value.startsWith('https:')) {
return getIdentifierFromURLImpl(tryParseURL(value));
}
}
const newurl = tryParseURL(url.href.substring(url.href.indexOf('http', 1)));
if(newurl) return getIdentifierFromURLImpl(newurl);
}
// fb group member badge
if (url.pathname.includes('/badge_member_list/')) return null;
if (url.href.indexOf('http', 1) != -1) {
const s = getQuery(url.search);
urlstr = null;
for (const key in s) {
if (s.hasOwnProperty(key)) {
const element = s[key];
if (element.startsWith('http:') || element.startsWith('https')) {
urlstr = element;
break;
}
}
}
if (urlstr == null) {
urlstr = url.href.substring(url.href.indexOf('http', 1))
}
try {
url = new URL(urlstr);
} catch (e) { }
}
let host = url.hostname;
if (isHostedOn(host, 'web.archive.org')) {
if (domainIs(host, 'web.archive.org')) {
const match = captureRegex(url.href, /\/web\/\w+\/(.*)/);
if (!match) return null;
return getIdentifierInternal('http://' + match);
return getIdentifierFromURLImpl(tryParseURL('http://' + match));
}
if (url.search && url.search.includes('http')) {
if (url.pathname.startsWith('/intl/')) return null; // facebook language switch links
for (const q of url.searchParams) {
if (q[1].startsWith('http')) return getIdentifierInternal(q[1]);
}
}
/*
if(host == 't.umblr.com'){
return getIdentifierInternal(url.searchParams.get('z'));
}
*/
if (host.startsWith('www.')) host = host.substring(4);
if (isHostedOn(host, 'facebook.com')) {
const s = getQuery(url.search);
if (domainIs(host, 'facebook.com')) {
const fbId = url.searchParams.get('id');
const p = url.pathname.replace('/pg/', '/');
return 'facebook.com/' + (s.id || takeFirstPathComponents(p, p.startsWith('/groups/') ? 2 : 1).substring(1));
}
if (isHostedOn(host, 'reddit.com')) {
return 'facebook.com/' + (fbId || getPartialPath(p, p.startsWith('/groups/') ? 2 : 1).substring(1));
} else if (domainIs(host, 'reddit.com')) {
const pathname = url.pathname.replace('/u/', '/user/');
if (!pathname.startsWith('/user/') && !pathname.startsWith('/r/')) return null;
if(pathname.includes('/comments/') && hostname == 'reddit.com') return null;
return 'reddit.com' + takeFirstPathComponents(pathname, 2);
}
if (isHostedOn(host, 'twitter.com')) {
return 'twitter.com' + takeFirstPathComponents(url.pathname, 1);
}
if (isHostedOn(host, 'youtube.com')) {
return 'reddit.com' + getPartialPath(pathname, 2);
} else if (domainIs(host, 'twitter.com')) {
return 'twitter.com' + getPartialPath(url.pathname, 1);
} else if (domainIs(host, 'youtube.com')) {
const pathname = url.pathname.replace('/c/', '/user/');
if (!pathname.startsWith('/user/') && !pathname.startsWith('/channel/')) return null;
return 'youtube.com' + takeFirstPathComponents(pathname, 2);
}
if (isHostedOn(host, 'disqus.com') && url.pathname.startsWith('/by/')) {
return 'disqus.com' + takeFirstPathComponents(url.pathname, 2);
}
if (isHostedOn(host, 'medium.com')) {
return 'medium.com' + takeFirstPathComponents(url.pathname.replace('/t/', '/'), 1);
}
if (isHostedOn(host, 'tumblr.com')) {
return 'youtube.com' + getPartialPath(pathname, 2);
} else if (domainIs(host, 'disqus.com') && url.pathname.startsWith('/by/')) {
return 'disqus.com' + getPartialPath(url.pathname, 2);
} else if (domainIs(host, 'medium.com')) {
return 'medium.com' + getPartialPath(url.pathname.replace('/t/', '/'), 1);
} else if (domainIs(host, 'tumblr.com')) {
if (url.pathname.startsWith('/register/follow/')) {
const name = takeNthPathComponent(url.pathname, 2);
const name = getPathPart(url.pathname, 2);
return name ? name + '.tumblr.com' : null;
}
if (host != 'www.tumblr.com' && host != 'assets.tumblr.com' && host.indexOf('.media.') == -1) {
if (!url.pathname.startsWith('/tagged/')) return url.host;
}
return null;
}
if (isHostedOn(host, 'wikipedia.org') || isHostedOn(host, 'rationalwiki.org')) {
} else if (domainIs(host, 'wikipedia.org') || domainIs(host, 'rationalwiki.org')) {
if (url.hash || url.pathname.includes(':')) return null;
if (url.pathname.startsWith('/wiki/')) return 'wikipedia.org' + takeFirstPathComponents(url.pathname, 2);
if (url.pathname.startsWith('/wiki/')) return 'wikipedia.org' + getPartialPath(url.pathname, 2);
else return null;
}
if (host.indexOf('.blogspot.') != -1) {
} else if (host.indexOf('.blogspot.') != -1) {
const m = captureRegex(host, /([a-zA-Z0-9\-]*)\.blogspot/);
if (m) return m + '.blogspot.com';
else return null;
} else {
if (host.startsWith('m.')) host = host.substr(2);
return host;
}
let id = host;
if (id.startsWith('www.')) id = id.substr(4);
if (id.startsWith('m.')) id = id.substr(2);
return id;
}
@ -500,7 +445,7 @@ init();
var lastGeneratedLinkId = 0;
function getSnippet(node){
function getSnippet(node: HTMLElement){
while (node) {
var classList = node.classList;
if (hostname == 'facebook.com' && node.dataset && node.dataset.ftr) return node;
@ -517,7 +462,7 @@ function getSnippet(node){
}
browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
browser.runtime.onMessage.addListener<ShinigamiEyesMessage, ShinigamiEyesSubmission>((message, sender, sendResponse) => {
if (message.updateAllLabels) {
updateAllLabels(true);
@ -528,13 +473,13 @@ browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
var target = lastRightClickedElement; // message.elementId ? browser.menus.getTargetElement(message.elementId) : null;
while(target){
if(target.href) break;
if((<HTMLAnchorElement>target).href) break;
target = target.parentElement;
}
if (target && target.href != message.url) target = null;
if (target && (<HTMLAnchorElement>target).href != message.url) target = null;
var identifier = target ? getIdentifier(target) : getIdentifier(message.url);
var identifier = target ? getIdentifier(<HTMLAnchorElement>target) : getIdentifier(message.url);
if (!identifier) return;
message.identifier = identifier;
@ -545,7 +490,7 @@ browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
message.linkId = ++lastGeneratedLinkId;
if (target)
target.setAttribute('shinigami-eyes-link-id', lastGeneratedLinkId);
target.setAttribute('shinigami-eyes-link-id', '' + lastGeneratedLinkId);
message.snippet = snippet ? snippet.outerHTML : null;
var debugClass = 'shinigami-eyes-debug-snippet-highlight';

View File

@ -1,16 +1,39 @@
declare class BloomFilter {
constructor(data: Uint32Array, k: number);
test(key: string): boolean;
name: string;
name: LabelKind;
}
interface HTMLElement {
assignedCssLabel?: string
}
interface LabelToSolve {
element: HTMLAnchorElement
identifier: string
}
type LabelKind = 't-friendly' | 'transphobic' | 'none' | '';
type ShinigamiSubmission = {
mark: LabelKind
url: string
tabId: number
frameId: number
debug: number
interface ShinigamiEyesSubmission {
mark?: LabelKind
url?: string
tabId?: number
frameId?: number
debug?: number
identifier?: string
secondaryIdentifier?: string
version?: number
submissionId?: string
contextPage?: string
linkId?: number
snippet?: string
}
interface ShinigamiEyesCommand {
acceptClicked?: boolean
myself?: string
ids?: string[]
updateAllLabels?: boolean
}
type LabelMap = {[identifier: string]: LabelKind};
interface ShinigamiEyesMessage extends ShinigamiEyesSubmission, ShinigamiEyesCommand{
}
type ContextMenuCommand = 'mark-t-friendly' | 'mark-transphobic' | 'mark-none' | 'help';

View File

@ -1,5 +1,7 @@
{
"compilerOptions": {
"target": "es2017"
"target": "es2017",
"noImplicitAny": true,
"noImplicitReturns": true,
}
}

View File

@ -1,9 +1,9 @@
declare type Browser = {
runtime: {
sendMessage<TRequest, TResponse>(request: TRequest, response: (response: TResponse) => void);
sendMessage<TRequest, TResponse>(request: TRequest, response: (response: TResponse) => void): void;
onMessage: {
addListener(listener: (message, any, sendResponse) => void)
addListener<TRequest, TResponse>(listener: (message: TRequest, sender: MessageSender, sendResponse: (response: TResponse) => void) => void): void
}
}
@ -11,13 +11,13 @@ declare type Browser = {
local: BrowserStorage
}
tabs: {
remove(id: number)
remove(id: number): void
sendMessage<TRequest, TResponse>(tabId: number, request: TRequest, options?: {
frameId: number
}, callback?: (response: TResponse) => void)
}, callback?: (response: TResponse) => void): void
create(options: {
url: string
})
}): void
}
extension: {
getURL(relativeUrl: string): string
@ -36,13 +36,20 @@ declare type Browser = {
linkUrl: string
}, tab: {
id: number
}) => void)
}) => void): void
}
}
}
type MessageSender = {
tab?: {id: number};
frameId?: number;
id?: string;
url?: string;
tlsChannelId?: string;
};
declare type BrowserStorage = {
get(names: string[], callback: (obj: any) => void)
set(obj: { [name: string]: any });
get(names: string[], callback: (obj: any) => void): void
set(obj: { [name: string]: any }): void;
}
declare var browser: Browser;
declare var chrome: Browser;