Compare commits
No commits in common. "a84a8f8c1031e4e7070d3fae5b615f5af1adae2a" and "2bcf72f65234fb388148c3cb50d4d3cd4b43b592" have entirely different histories.
a84a8f8c10
...
2bcf72f652
32
mark.ts
32
mark.ts
@ -1,32 +0,0 @@
|
|||||||
import { Classifications, StolenDataEntry } from "./stolen-data-entry";
|
|
||||||
|
|
||||||
export default class Mark {
|
|
||||||
classification: keyof typeof Classifications;
|
|
||||||
constructor(public entry: StolenDataEntry, public key: string) {
|
|
||||||
this.classification = entry.classification;
|
|
||||||
}
|
|
||||||
|
|
||||||
getParsedValue() {
|
|
||||||
return this.entry.getParsedValue(this.key);
|
|
||||||
}
|
|
||||||
|
|
||||||
get shorthost() {
|
|
||||||
return this.entry.request.shorthost;
|
|
||||||
}
|
|
||||||
|
|
||||||
get source() {
|
|
||||||
return this.entry.source;
|
|
||||||
}
|
|
||||||
|
|
||||||
get name() {
|
|
||||||
return this.entry.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
get originalURL() {
|
|
||||||
return this.entry.request.originalURL;
|
|
||||||
}
|
|
||||||
|
|
||||||
get valuePreview(): string {
|
|
||||||
return this.entry.getValuePreview(this.key);
|
|
||||||
}
|
|
||||||
}
|
|
17
memory.ts
17
memory.ts
@ -1,11 +1,10 @@
|
|||||||
import ExtendedRequest from "./extended-request";
|
import ExtendedRequest from "./extended-request";
|
||||||
import { getshorthost, makeThrottle } from "./util";
|
import { getshorthost } from "./util";
|
||||||
import { EventEmitter } from "events";
|
import { EventEmitter } from "events";
|
||||||
import { RequestCluster } from "./request-cluster";
|
import { RequestCluster } from "./request-cluster";
|
||||||
|
|
||||||
export default class Memory extends EventEmitter {
|
export default class Memory extends EventEmitter {
|
||||||
origin_to_history = {} as Record<string, Record<string, RequestCluster>>;
|
origin_to_history = {} as Record<string, Record<string, RequestCluster>>;
|
||||||
private throttle = makeThrottle(200);
|
|
||||||
async register(request: ExtendedRequest) {
|
async register(request: ExtendedRequest) {
|
||||||
await request.init();
|
await request.init();
|
||||||
console.log("registering request for", request.origin);
|
console.log("registering request for", request.origin);
|
||||||
@ -35,20 +34,6 @@ export default class Memory extends EventEmitter {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
emit(eventName: string, immediate = false) {
|
|
||||||
try {
|
|
||||||
if (immediate) {
|
|
||||||
super.emit(eventName);
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
this.throttle(() => super.emit(eventName));
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} catch (e) {
|
|
||||||
debugger;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getClustersForOrigin(origin: string): Record<string, RequestCluster> {
|
getClustersForOrigin(origin: string): Record<string, RequestCluster> {
|
||||||
return this.origin_to_history[origin] || {};
|
return this.origin_to_history[origin] || {};
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@ import { Classifications, Sources } from "../stolen-data-entry";
|
|||||||
const emailClassifications: Record<keyof typeof Classifications, string> = {
|
const emailClassifications: Record<keyof typeof Classifications, string> = {
|
||||||
id: "sztucznie nadane mi ID",
|
id: "sztucznie nadane mi ID",
|
||||||
history: "część mojej historii przeglądania",
|
history: "część mojej historii przeglądania",
|
||||||
location: "informacje na temat mojej lokalizacji geograficznej",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const emailSources: Record<Sources, string> = {
|
const emailSources: Record<Sources, string> = {
|
||||||
@ -26,22 +25,22 @@ export default function DomainSummary({
|
|||||||
<ul>
|
<ul>
|
||||||
<li>Mój adres IP</li>
|
<li>Mój adres IP</li>
|
||||||
{cluster
|
{cluster
|
||||||
.getMarks()
|
.getMarkedEntries()
|
||||||
.sort((markA, markB) =>
|
.sort((entryA, entryB) => (entryA.value > entryB.value ? -1 : 1))
|
||||||
markA.entry.value > markB.entry.value ? -1 : 1
|
.reduce((acc, entry, index, arr) => {
|
||||||
)
|
if (index === 0) {
|
||||||
.map((mark) => (
|
return [entry];
|
||||||
|
}
|
||||||
|
if (entry.value != arr[index - 1].value) {
|
||||||
|
acc.push(entry);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, [])
|
||||||
|
.map((entry) => (
|
||||||
<li>
|
<li>
|
||||||
{emailClassifications[mark.classification]}{" "}
|
{emailClassifications[entry.classification]}{" "}
|
||||||
{emailSources[mark.source]} (nazwa: {mark.name},{" "}
|
{emailSources[entry.source]}
|
||||||
{mark.key ? (
|
(<code>{entry.name.trim()}</code>)
|
||||||
<>
|
|
||||||
pozycja <code>{mark.key}</code>,
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
""
|
|
||||||
)}
|
|
||||||
wartość: <code>{mark.valuePreview}</code>)
|
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -1,27 +1,24 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import Mark from "../mark";
|
|
||||||
import { RequestCluster } from "../request-cluster";
|
import { RequestCluster } from "../request-cluster";
|
||||||
|
import { StolenDataEntry } from "../stolen-data-entry";
|
||||||
import { getDate, toBase64 } from "../util";
|
import { getDate, toBase64 } from "../util";
|
||||||
import DomainSummary from "./domain-summary";
|
import DomainSummary from "./domain-summary";
|
||||||
|
|
||||||
type PopupState = "not_clicked" | "clicked_but_invalid";
|
type PopupState = "not_clicked" | "clicked_but_invalid";
|
||||||
|
|
||||||
export default function EmailTemplate({
|
export default function EmailTemplate({
|
||||||
marks,
|
marked_entries,
|
||||||
clusters,
|
clusters,
|
||||||
version,
|
|
||||||
}: {
|
}: {
|
||||||
marks: Mark[];
|
marked_entries: StolenDataEntry[];
|
||||||
clusters: Record<string, RequestCluster>;
|
clusters: Record<string, RequestCluster>;
|
||||||
version: number;
|
|
||||||
}): JSX.Element {
|
}): JSX.Element {
|
||||||
const [popupState, setPopupState] = useState<PopupState>("not_clicked");
|
const [popupState, setPopupState] = useState<PopupState>("not_clicked");
|
||||||
const [acceptAllName, setAcceptAllName] = useState<string>(
|
const [acceptAllName, setAcceptAllName] = useState<string>(
|
||||||
"Zaakceptuj wszystkie"
|
"Zaakceptuj wszystkie"
|
||||||
);
|
);
|
||||||
const [popupScreenshotBase64, setPopupScreenshotBase64] = useState<string>(
|
const [popupScreenshotBase64, setPopupScreenshotBase64] =
|
||||||
null
|
useState<string>(null);
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
@ -67,8 +64,8 @@ export default function EmailTemplate({
|
|||||||
) : null}
|
) : null}
|
||||||
<p>
|
<p>
|
||||||
Dzień dobry, w dniu {getDate()} odwiedziłem stronę{" "}
|
Dzień dobry, w dniu {getDate()} odwiedziłem stronę{" "}
|
||||||
{marks[0].originalURL}. Strona ta wysłała moje dane osobowe do podmiotów
|
{marked_entries[0].request.originalURL}. Strona ta wysłała moje dane
|
||||||
trzecich - bez mojej zgody.{" "}
|
osobowe do podmiotów trzecich - bez mojej zgody.{" "}
|
||||||
</p>
|
</p>
|
||||||
<ul>
|
<ul>
|
||||||
{Object.values(clusters)
|
{Object.values(clusters)
|
||||||
@ -77,15 +74,10 @@ export default function EmailTemplate({
|
|||||||
<DomainSummary cluster={cluster} />
|
<DomainSummary cluster={cluster} />
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
<p>
|
|
||||||
{" "}
|
|
||||||
Dane te zostały wysłane przez Państwa stronę - a mówiąc dokładniej,
|
|
||||||
przez zamieszczone przez Państwa na tej stronie skrypty.
|
|
||||||
</p>
|
|
||||||
{popupState === "not_clicked" ? (
|
{popupState === "not_clicked" ? (
|
||||||
<p>
|
<p>
|
||||||
Nastąpiło to, zanim zdążyłem w ogóle przeczytać treść wyskakującego
|
Dane te zostały wysłane przez Państwa stronę, zanim zdążyłem w ogóle
|
||||||
okienka ze zgodami.
|
przeczytać treść wyskakującego okienka ze zgodami.
|
||||||
</p>
|
</p>
|
||||||
) : null}
|
) : null}
|
||||||
{popupState === "clicked_but_invalid" ? (
|
{popupState === "clicked_but_invalid" ? (
|
||||||
@ -153,10 +145,12 @@ export default function EmailTemplate({
|
|||||||
procesów przetwarzania danych.
|
procesów przetwarzania danych.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Niniejszym zwracam się także z żądaniem ujawnienia tożsamości podmiotów,
|
Niniejszym zwracam się także z żądaniem wycofania przesłanych przez
|
||||||
które są właścicielami wyżej wymienionych domen, abym mógł zapoznać się
|
Państwa stronę moich danych osobowych z baz wyżej wymienionych podmiotów
|
||||||
z ich politykami prywatności i zwrócić się do tych podmiotów o usunięcie
|
oraz przesłania potwierdzenia uwiarygadniającego pomyślne wycofanie tych
|
||||||
z ich baz wysłanych przez Państwa stronę moich danych.
|
danych. Proszę też o przesłanie tożsamości podmiotów, które są
|
||||||
|
właścicielami wyżej wymienionych domen, abym mógł zapoznać się z ich
|
||||||
|
politykami prywatności.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Proszę też o wysłanie kopii danych zebranych na mój temat i wysłanych do
|
Proszę też o wysłanie kopii danych zebranych na mój temat i wysłanych do
|
||||||
|
@ -1,18 +1,20 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { HAREntry } from "../extended-request";
|
import { HAREntry } from "../extended-request";
|
||||||
import Mark from "../mark";
|
import { StolenDataEntry } from "../stolen-data-entry";
|
||||||
import { getshorthost, unique } from "../util";
|
import { getshorthost, unique } from "../util";
|
||||||
|
|
||||||
function handleNewFile(
|
function handleNewFile(
|
||||||
element: HTMLInputElement,
|
element: HTMLInputElement,
|
||||||
marks: Mark[],
|
marked_entries: StolenDataEntry[],
|
||||||
setFiltered: (Blob) => void
|
setFiltered: (Blob) => void
|
||||||
): void {
|
): void {
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
reader.addEventListener("load", () => {
|
reader.addEventListener("load", () => {
|
||||||
const content = JSON.parse(reader.result as string);
|
const content = JSON.parse(reader.result as string);
|
||||||
content.log.entries = content.log.entries.filter((har_entry: HAREntry) =>
|
content.log.entries = content.log.entries.filter((har_entry: HAREntry) =>
|
||||||
marks.some((mark) => mark.entry.matchesHAREntry(har_entry))
|
marked_entries.some((stolen_entry) =>
|
||||||
|
stolen_entry.matchesHAREntry(har_entry)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
setFiltered(
|
setFiltered(
|
||||||
new Blob([JSON.stringify(content)], { type: "application/json" })
|
new Blob([JSON.stringify(content)], { type: "application/json" })
|
||||||
@ -21,8 +23,8 @@ function handleNewFile(
|
|||||||
reader.readAsText(element.files[0]);
|
reader.readAsText(element.files[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateFakeHAR(marks: Mark[]) {
|
function generateFakeHAR(marked_entries: StolenDataEntry[]) {
|
||||||
const requests = marks.map((mark) => mark.entry.request);
|
const requests = marked_entries.map((entry) => entry.request);
|
||||||
return {
|
return {
|
||||||
log: {
|
log: {
|
||||||
version: "1.2",
|
version: "1.2",
|
||||||
@ -50,14 +52,14 @@ function generateFakeHAR(marks: Mark[]) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function HARConverter({ marks }: { marks: Mark[] }) {
|
export default function HARConverter({
|
||||||
|
marked_entries,
|
||||||
|
}: {
|
||||||
|
marked_entries: StolenDataEntry[];
|
||||||
|
}) {
|
||||||
const [filtered, setFiltered] = useState<Blob | null>(null);
|
const [filtered, setFiltered] = useState<Blob | null>(null);
|
||||||
const [filename, setFilename] = useState("");
|
const [filename, setFilename] = useState("");
|
||||||
const [fakeHAR, setFakeHAR] = useState<ReturnType<typeof generateFakeHAR>>();
|
const fakeHAR = generateFakeHAR(marked_entries);
|
||||||
useEffect(() => {
|
|
||||||
setFakeHAR(generateFakeHAR(marks));
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<input
|
<input
|
||||||
@ -65,7 +67,7 @@ export default function HARConverter({ marks }: { marks: Mark[] }) {
|
|||||||
accept=".har"
|
accept=".har"
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setFilename(e.target.files[0].name);
|
setFilename(e.target.files[0].name);
|
||||||
handleNewFile(e.target, marks, setFiltered);
|
handleNewFile(e.target, marked_entries, setFiltered);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{(filtered && (
|
{(filtered && (
|
||||||
@ -82,7 +84,7 @@ export default function HARConverter({ marks }: { marks: Mark[] }) {
|
|||||||
new Blob([JSON.stringify(fakeHAR)], { type: "application/json" })
|
new Blob([JSON.stringify(fakeHAR)], { type: "application/json" })
|
||||||
)}
|
)}
|
||||||
download={`${getshorthost(
|
download={`${getshorthost(
|
||||||
marks[0].originalURL
|
marked_entries[0].request.originalURL
|
||||||
)}-${new Date().toJSON()}-trimmed.har`}
|
)}-${new Date().toJSON()}-trimmed.har`}
|
||||||
>
|
>
|
||||||
Pobierz "zfałszowany" HAR
|
Pobierz "zfałszowany" HAR
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import ReactDOM from "react-dom";
|
import ReactDOM from "react-dom";
|
||||||
import { getMemory } from "../memory";
|
import { getMemory } from "../memory";
|
||||||
import { Classifications } from "../stolen-data-entry";
|
|
||||||
import { reduceConcat, useEmitter } from "../util";
|
|
||||||
import EmailTemplate from "./email-template";
|
import EmailTemplate from "./email-template";
|
||||||
import HARConverter from "./har-converter";
|
import HARConverter from "./har-converter";
|
||||||
|
|
||||||
@ -10,20 +8,14 @@ function Report() {
|
|||||||
const origin = new URL(document.location.toString()).searchParams.get(
|
const origin = new URL(document.location.toString()).searchParams.get(
|
||||||
"origin"
|
"origin"
|
||||||
);
|
);
|
||||||
const [counter, setCounter] = useEmitter(getMemory());
|
|
||||||
function refresh() {
|
|
||||||
setCounter((c) => c + 1);
|
|
||||||
}
|
|
||||||
const clusters = getMemory().getClustersForOrigin(origin);
|
const clusters = getMemory().getClustersForOrigin(origin);
|
||||||
const marks = Object.values(clusters)
|
const marked_entries = Object.values(clusters)
|
||||||
.map((cluster) => cluster.getMarkedRequests())
|
.map((cluster) => cluster.getMarkedRequests())
|
||||||
.reduce(reduceConcat, [])
|
.reduce((a, b) => a.concat(b), [])
|
||||||
.map((request) => request.getMarkedEntries())
|
.map((request) => request.getMarkedEntries())
|
||||||
.reduce(reduceConcat, [])
|
.reduce((a, b) => a.concat(b), []);
|
||||||
.map((entry) => entry.marks)
|
|
||||||
.reduce(reduceConcat, []);
|
|
||||||
return (
|
return (
|
||||||
<div {...{ "data-version": counter }}>
|
<div>
|
||||||
<h1>Generuj treść maila dla {origin}</h1>
|
<h1>Generuj treść maila dla {origin}</h1>
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
@ -35,46 +27,34 @@ function Report() {
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{marks.map((mark) => (
|
{marked_entries.map((entry) => (
|
||||||
<tr
|
<tr
|
||||||
key={mark.entry.request.originalURL + ";" + mark.key}
|
|
||||||
style={{
|
style={{
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
mark.classification == "id" ? "yellow" : "white",
|
entry.classification == "id" ? "yellow" : "white",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<td>{mark.shorthost}</td>
|
<td>{entry.request.shorthost}</td>
|
||||||
<td style={{ overflowWrap: "anywhere" }}>
|
<td style={{ overflowWrap: "anywhere" }}>
|
||||||
{mark.source}:{mark.name}
|
{entry.source}:{entry.name}
|
||||||
{mark.key}
|
{entry.markedKeys.join(",")}
|
||||||
</td>
|
</td>
|
||||||
<td
|
<td
|
||||||
style={{
|
style={{
|
||||||
width: "400px",
|
width: "400px",
|
||||||
overflowWrap: "anywhere",
|
overflowWrap: "anywhere",
|
||||||
backgroundColor: mark.entry.isRelatedToID()
|
backgroundColor: entry.isRelatedToID()
|
||||||
? "#ffff0054"
|
? "#ffff0054"
|
||||||
: "white",
|
: "white",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{mark.valuePreview}
|
{entry.value}
|
||||||
{/* always gonna have
|
|
||||||
one key, because unwrapEntry is calle above */}
|
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select
|
<select value={entry.classification}>
|
||||||
value={mark.classification}
|
|
||||||
onChange={(e) => {
|
|
||||||
mark.classification = e.target
|
|
||||||
.value as keyof typeof Classifications;
|
|
||||||
console.log("changed classification!");
|
|
||||||
refresh();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{[
|
{[
|
||||||
["history", "Historia przeglądania"],
|
["history", "Historia przeglądania"],
|
||||||
["id", "Sztucznie nadane id"],
|
["id", "Sztucznie nadane id"],
|
||||||
["location", "Lokalizacja"],
|
|
||||||
].map(([key, name]) => (
|
].map(([key, name]) => (
|
||||||
<option key={key} value={key}>
|
<option key={key} value={key}>
|
||||||
{name}
|
{name}
|
||||||
@ -86,8 +66,8 @@ function Report() {
|
|||||||
))}
|
))}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<EmailTemplate {...{ marks, clusters, version: counter }} />
|
<EmailTemplate {...{ marked_entries, clusters }} />
|
||||||
<HARConverter {...{ marks }} />
|
<HARConverter {...{ marked_entries }} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -105,7 +105,7 @@ export class RequestCluster extends EventEmitter {
|
|||||||
return this.requests.some((request) => request.hasMark());
|
return this.requests.some((request) => request.hasMark());
|
||||||
}
|
}
|
||||||
|
|
||||||
getMarkedEntries(): StolenDataEntry[] {
|
getMarkedEntries() {
|
||||||
return this.requests
|
return this.requests
|
||||||
.map((request) => request.getMarkedEntries())
|
.map((request) => request.getMarkedEntries())
|
||||||
.reduce(reduceConcat, []);
|
.reduce(reduceConcat, []);
|
||||||
@ -114,12 +114,4 @@ export class RequestCluster extends EventEmitter {
|
|||||||
exposesOrigin() {
|
exposesOrigin() {
|
||||||
return this.requests.some((request) => request.exposesOrigin());
|
return this.requests.some((request) => request.exposesOrigin());
|
||||||
}
|
}
|
||||||
|
|
||||||
getMarks() {
|
|
||||||
return this.requests
|
|
||||||
.map((request) => request.getMarkedEntries())
|
|
||||||
.reduce(reduceConcat, [])
|
|
||||||
.map((entry) => entry.marks)
|
|
||||||
.reduce(reduceConcat, []);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -118,14 +118,7 @@ export default function StolenDataCluster({
|
|||||||
key={origin + cluster.id + entry.getUniqueKey()}
|
key={origin + cluster.id + entry.getUniqueKey()}
|
||||||
data-key={origin + cluster.id + entry.getUniqueKey()}
|
data-key={origin + cluster.id + entry.getUniqueKey()}
|
||||||
>
|
>
|
||||||
<th
|
<th style={{ width: "100px", overflowWrap: "anywhere" }}>
|
||||||
style={{
|
|
||||||
width: "100px",
|
|
||||||
overflowWrap: "anywhere",
|
|
||||||
border: entry.hasMark("") ? "2px solid red" : "",
|
|
||||||
}}
|
|
||||||
onClick={() => entry.addMark("")}
|
|
||||||
>
|
|
||||||
{entry.getNames().map(hyphenate).join(", ")}
|
{entry.getNames().map(hyphenate).join(", ")}
|
||||||
</th>
|
</th>
|
||||||
<td>{entry.getSources().map((source) => icons[source])}</td>
|
<td>{entry.getSources().map((source) => icons[source])}</td>
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { TCModel } from "@iabtcf/core";
|
import { TCModel } from "@iabtcf/core";
|
||||||
import ExtendedRequest, { HAREntry } from "./extended-request";
|
import ExtendedRequest, { HAREntry } from "./extended-request";
|
||||||
import Mark from "./mark";
|
|
||||||
import { getMemory } from "./memory";
|
import { getMemory } from "./memory";
|
||||||
import {
|
import {
|
||||||
getshorthost,
|
getshorthost,
|
||||||
@ -16,11 +15,8 @@ export type Sources = "cookie" | "pathname" | "queryparams" | "header";
|
|||||||
export const Classifications = <const>{
|
export const Classifications = <const>{
|
||||||
id: "Sztucznie nadane ID",
|
id: "Sztucznie nadane ID",
|
||||||
history: "Część historii przeglądania",
|
history: "Część historii przeglądania",
|
||||||
location: "Informacje na temat mojego położenia",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const ID_PREVIEW_MAX_LENGTH = 20;
|
|
||||||
|
|
||||||
const id = (function* id() {
|
const id = (function* id() {
|
||||||
let i = 0;
|
let i = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
@ -33,7 +29,7 @@ export class StolenDataEntry {
|
|||||||
public isIAB = false;
|
public isIAB = false;
|
||||||
public iab: TCModel | null = null;
|
public iab: TCModel | null = null;
|
||||||
public id: number;
|
public id: number;
|
||||||
public marks: Mark[] = [];
|
public markedKeys: string[] = [];
|
||||||
public classification: keyof typeof Classifications;
|
public classification: keyof typeof Classifications;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@ -82,7 +78,6 @@ export class StolenDataEntry {
|
|||||||
} else if (isURL(value)) {
|
} else if (isURL(value)) {
|
||||||
const url = new URL(value);
|
const url = new URL(value);
|
||||||
const object = {
|
const object = {
|
||||||
[Symbol.for("originalURL")]: value,
|
|
||||||
host: url.host,
|
host: url.host,
|
||||||
path: url.pathname,
|
path: url.pathname,
|
||||||
...Object.fromEntries(
|
...Object.fromEntries(
|
||||||
@ -97,7 +92,7 @@ export class StolenDataEntry {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getParsedValue(key_path: string): string | Record<string | symbol, unknown> {
|
getParsedValue(key_path: string): string | Record<string, unknown> {
|
||||||
let object = StolenDataEntry.parseValue(this.value);
|
let object = StolenDataEntry.parseValue(this.value);
|
||||||
for (const key of key_path.split(".")) {
|
for (const key of key_path.split(".")) {
|
||||||
if (key === "") continue;
|
if (key === "") continue;
|
||||||
@ -107,20 +102,20 @@ export class StolenDataEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
addMark(key: string) {
|
addMark(key: string) {
|
||||||
this.marks.push(new Mark(this, key));
|
this.markedKeys.push(key);
|
||||||
getMemory().emit("change", true); // to trigger rerender
|
getMemory().emit("change"); // to trigger rerender
|
||||||
}
|
}
|
||||||
|
|
||||||
hasMark(key?: string) {
|
hasMark(key?: string) {
|
||||||
if (key) {
|
if (key) {
|
||||||
return this.marks.some((k) => k.key == key);
|
return this.markedKeys.some((k) => k == key);
|
||||||
} else {
|
} else {
|
||||||
return this.marks.length > 0;
|
return this.markedKeys.length > 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
removeMark(key: string) {
|
removeMark(key: string) {
|
||||||
this.marks = this.marks.filter((mark) => mark.key != key);
|
this.markedKeys = this.markedKeys.filter((e) => e != key);
|
||||||
getMemory().emit("change"); // to trigger rerender
|
getMemory().emit("change"); // to trigger rerender
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,29 +154,15 @@ export class StolenDataEntry {
|
|||||||
matchesHAREntry(har: HAREntry): boolean {
|
matchesHAREntry(har: HAREntry): boolean {
|
||||||
return this.request.matchesHAREntry(har);
|
return this.request.matchesHAREntry(har);
|
||||||
}
|
}
|
||||||
|
|
||||||
getValuePreview(key = ""): string {
|
|
||||||
const value = this.getParsedValue(key);
|
|
||||||
const str = value.toString();
|
|
||||||
if (this.classification == "id") {
|
|
||||||
return (
|
|
||||||
str.slice(0, Math.min(str.length / 3, ID_PREVIEW_MAX_LENGTH)) + "(...)"
|
|
||||||
);
|
|
||||||
} else if (typeof value === "object" && value[Symbol.for("originalURL")]) {
|
|
||||||
return value[Symbol.for("originalURL")] as string;
|
|
||||||
} else {
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class MergedStolenDataEntry {
|
export class MergedStolenDataEntry {
|
||||||
constructor(public entries: StolenDataEntry[]) {
|
constructor(public entries: StolenDataEntry[]) {
|
||||||
const all_marks = unique(
|
const all_marks = unique(
|
||||||
entries.map((entry) => entry.marks).reduce(reduceConcat, [])
|
entries.map((entry) => entry.markedKeys).reduce(reduceConcat, [])
|
||||||
);
|
);
|
||||||
for (const entry of entries) {
|
for (const entry of entries) {
|
||||||
entry.marks = all_marks;
|
entry.markedKeys = all_marks;
|
||||||
}
|
}
|
||||||
// getMemory().emit("change"); // to trigger render
|
// getMemory().emit("change"); // to trigger render
|
||||||
}
|
}
|
||||||
@ -229,7 +210,7 @@ export class MergedStolenDataEntry {
|
|||||||
|
|
||||||
getMarkedValues() {
|
getMarkedValues() {
|
||||||
return this.entries
|
return this.entries
|
||||||
.map((entry) => entry.marks)
|
.map((entry) => entry.markedKeys)
|
||||||
.reduce((a, b) => a.concat(b), []);
|
.reduce((a, b) => a.concat(b), []);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"lib": ["es2017", "dom", "es2019"],
|
"lib": ["es2017", "dom", "es2019"],
|
||||||
"typeRoots": ["node_modules/@types", "node_modules/web-ext-types"],
|
"typeRoots": ["node_modules/@types", "node_modules/web-ext-types"],
|
||||||
"target": "es2019",
|
|
||||||
"outDir": "lib"
|
"outDir": "lib"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
18
util.ts
18
util.ts
@ -138,21 +138,3 @@ export function toBase64(file: File): Promise<string> {
|
|||||||
FR.readAsDataURL(file);
|
FR.readAsDataURL(file);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function makeThrottle(interval: number) {
|
|
||||||
let last_emit = 0;
|
|
||||||
function emit(callback: () => void) {
|
|
||||||
if (Date.now() - last_emit > interval) {
|
|
||||||
callback();
|
|
||||||
last_emit = Date.now();
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return function (callback: () => void) {
|
|
||||||
if (!emit(callback)) {
|
|
||||||
setTimeout(() => emit(callback), interval);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user