Initial commit
commit
c57a3c2d1b
@ -0,0 +1,3 @@
|
||||
/node_modules/
|
||||
/@types/
|
||||
/lib/
|
@ -0,0 +1,14 @@
|
||||
{
|
||||
useTabs: true,
|
||||
tabWidth: 4,
|
||||
trailingComma: "es5",
|
||||
"overrides": [
|
||||
{
|
||||
"files": "*.yml",
|
||||
"options": {
|
||||
"tabWidth": 2,
|
||||
"useTabs": false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,163 @@
|
||||
{
|
||||
"name": "poznan-sm-submit",
|
||||
"version": "0.1.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@types/node": {
|
||||
"version": "14.14.19",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.19.tgz",
|
||||
"integrity": "sha512-4nhBPStMK04rruRVtVc6cDqhu7S9GZai0fpXgPXrFpcPX6Xul8xnrjSdGB4KPBVYG/R5+fXWdCM8qBoiULWGPQ=="
|
||||
},
|
||||
"@types/tough-cookie": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.0.tgz",
|
||||
"integrity": "sha512-I99sngh224D0M7XgW1s120zxCt3VYQ3IQsuw3P3jbq5GG4yc79+ZjyKznyOGIQrflfylLgcfekeZW/vk0yng6A=="
|
||||
},
|
||||
"async-spawner": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/async-spawner/-/async-spawner-0.1.0.tgz",
|
||||
"integrity": "sha512-I/5cYWGgH5LJiHqWTwPLu7yM4XqT7dtMo77bPWtdtmOqbT9xpxF/ckasT2kdubMw8D0QD6/nSTPx+ZjvbhW/jQ==",
|
||||
"requires": {
|
||||
"@types/node": "^14.14.19",
|
||||
"emittery": "^0.8.0"
|
||||
}
|
||||
},
|
||||
"asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
|
||||
},
|
||||
"axios": {
|
||||
"version": "0.21.1",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
|
||||
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
|
||||
"requires": {
|
||||
"follow-redirects": "^1.10.0"
|
||||
}
|
||||
},
|
||||
"axios-cookiejar-support": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/axios-cookiejar-support/-/axios-cookiejar-support-1.0.1.tgz",
|
||||
"integrity": "sha512-IZJxnAJ99XxiLqNeMOqrPbfR7fRyIfaoSLdPUf4AMQEGkH8URs0ghJK/xtqBsD+KsSr3pKl4DEQjCn834pHMig==",
|
||||
"requires": {
|
||||
"is-redirect": "^1.0.0",
|
||||
"pify": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"requires": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
|
||||
},
|
||||
"emittery": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.0.tgz",
|
||||
"integrity": "sha512-XMGToId3CejfmZg/0qOzdTT3WFuAN8fQYtcKXccabRfCzGiWMSTydMshHGLyx9C/ejMl4nw9tvqrn12QVFPIUg=="
|
||||
},
|
||||
"epsg-index": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/epsg-index/-/epsg-index-1.0.0.tgz",
|
||||
"integrity": "sha512-7EcEC97QaNzSKakpc6HgVdxBc7G1vEuNRIygjVXBvrLA+t8+4QlK6jisf0g552eSzBIAkx0IRmd/CWJKLc/W5A=="
|
||||
},
|
||||
"follow-redirects": {
|
||||
"version": "1.13.1",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.1.tgz",
|
||||
"integrity": "sha512-SSG5xmZh1mkPGyKzjZP8zLjltIfpW32Y5QpdNJyjcfGxK3qo3NDDkZOZSFiGn1A6SclQxY9GzEwAHQ3dmYRWpg=="
|
||||
},
|
||||
"form-data": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz",
|
||||
"integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==",
|
||||
"requires": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"mime-types": "^2.1.12"
|
||||
}
|
||||
},
|
||||
"is-redirect": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz",
|
||||
"integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ="
|
||||
},
|
||||
"mgrs": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/mgrs/-/mgrs-1.0.0.tgz",
|
||||
"integrity": "sha1-+5FYjnjJACVnI5XLQLJffNatGCk="
|
||||
},
|
||||
"mime-db": {
|
||||
"version": "1.45.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz",
|
||||
"integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w=="
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.28",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz",
|
||||
"integrity": "sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==",
|
||||
"requires": {
|
||||
"mime-db": "1.45.0"
|
||||
}
|
||||
},
|
||||
"pify": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz",
|
||||
"integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA=="
|
||||
},
|
||||
"proj4": {
|
||||
"version": "2.6.3",
|
||||
"resolved": "https://registry.npmjs.org/proj4/-/proj4-2.6.3.tgz",
|
||||
"integrity": "sha512-XRqnLmHWlvi7jqKNTqaOUrVy72JEtOUrnlLki99yZUOSvcSeBaZ1I/EGnQ2LzplSbjSrebGAdikqCLeCxC/YEg==",
|
||||
"requires": {
|
||||
"mgrs": "1.0.0",
|
||||
"wkt-parser": "^1.2.4"
|
||||
}
|
||||
},
|
||||
"psl": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
|
||||
"integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ=="
|
||||
},
|
||||
"punycode": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
|
||||
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz",
|
||||
"integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==",
|
||||
"requires": {
|
||||
"psl": "^1.1.33",
|
||||
"punycode": "^2.1.1",
|
||||
"universalify": "^0.1.2"
|
||||
}
|
||||
},
|
||||
"transform-coordinates": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/transform-coordinates/-/transform-coordinates-1.0.0.tgz",
|
||||
"integrity": "sha512-6kZMpg+TBThUO7lbt9lWbM/DiRED+lczpjjRN3R7CB0xTEfVYqx3X9pBZx0gpihdmiUZNghArYKBiZNG4XDFYA==",
|
||||
"requires": {
|
||||
"epsg-index": "^1.0.0",
|
||||
"proj4": "^2.4.4"
|
||||
}
|
||||
},
|
||||
"universalify": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
|
||||
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="
|
||||
},
|
||||
"wkt-parser": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/wkt-parser/-/wkt-parser-1.2.4.tgz",
|
||||
"integrity": "sha512-ZzKnc7ml/91fOPh5bANBL4vUlWPIYYv11waCtWTkl2TRN+LEmBg60Q1MA8gqV4hEp4MGfSj9JiHz91zw/gTDXg=="
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "poznan-sm-submit",
|
||||
"version": "0.1.0",
|
||||
"description": "submit report to Poznań's Straż Miejska",
|
||||
"main": "dist/index.js",
|
||||
"types": "./@types/index.d.ts",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"watch": "npm run build -- --watch"
|
||||
},
|
||||
"author": "Kuba Orlik",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@types/node": "^14.14.19",
|
||||
"@types/tough-cookie": "^4.0.0",
|
||||
"async-spawner": "^0.1.0",
|
||||
"axios": "^0.21.1",
|
||||
"axios-cookiejar-support": "^1.0.1",
|
||||
"form-data": "^3.0.0",
|
||||
"tough-cookie": "^4.0.0",
|
||||
"transform-coordinates": "^1.0.0"
|
||||
}
|
||||
}
|
@ -0,0 +1,182 @@
|
||||
import { promisify } from "util";
|
||||
import spawn from "async-spawner";
|
||||
import FormData from "form-data";
|
||||
import axios from "axios";
|
||||
import tough from "tough-cookie";
|
||||
import fs from "fs";
|
||||
import axiosCookieJarSupport from "axios-cookiejar-support";
|
||||
import * as path from "path";
|
||||
|
||||
import { LocationData, toCityCoordinates } from "./location";
|
||||
import months from "./months";
|
||||
|
||||
axiosCookieJarSupport(axios);
|
||||
|
||||
const SM_URL =
|
||||
"https://www.um.poznan.pl/mim/forms/sm_zgloszenia.html?instance=poznan_sm";
|
||||
|
||||
const headers = {
|
||||
Accept:
|
||||
"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
|
||||
Host: "www.um.poznan.pl",
|
||||
Origin: "https://www.um.poznan.pl",
|
||||
Referer:
|
||||
"https://www.um.poznan.pl/mim/forms/sm_zgloszenia.html?instance=poznan_sm",
|
||||
"User-Agent":
|
||||
"Mozilla/5.0 (X11; Linux x86_64; rv:72.0) Gecko/20100101 Firefox/72.0",
|
||||
};
|
||||
|
||||
const minimal_data = {
|
||||
lhs: "eurzad",
|
||||
instance: "poznan_sm",
|
||||
};
|
||||
|
||||
function formatTimestamp(timestamp: Date) {
|
||||
const date_str = `${timestamp.getDate()} ${
|
||||
months[timestamp.getMonth()]
|
||||
} ${timestamp.getFullYear()}`;
|
||||
const time = `${timestamp.getHours()}:${
|
||||
timestamp.getMinutes() < 10 ? "0" : ""
|
||||
}${timestamp.getMinutes()}`;
|
||||
return [date_str, time];
|
||||
}
|
||||
|
||||
type ContactDetails = {
|
||||
email: string;
|
||||
imie_nazwisko: string;
|
||||
adres: string;
|
||||
};
|
||||
|
||||
export async function submit(
|
||||
location: LocationData,
|
||||
reason: string,
|
||||
photos: Array<string>,
|
||||
timestamp: Date,
|
||||
contact_details: ContactDetails
|
||||
) {
|
||||
if (location.address.includes("\n")) {
|
||||
throw new Error("no newlines allowed in address");
|
||||
}
|
||||
const { x, y } = toCityCoordinates(location.coordinates);
|
||||
|
||||
const jar = new tough.CookieJar();
|
||||
|
||||
const transport = axios.create({
|
||||
withCredentials: true,
|
||||
});
|
||||
|
||||
await transport.get(SM_URL, {
|
||||
headers,
|
||||
jar,
|
||||
});
|
||||
|
||||
const subject = `Nieprawidłowo zaparkowany samochód - ${location.address}`;
|
||||
|
||||
const [date_str, hour] = formatTimestamp(timestamp);
|
||||
|
||||
const body = `Samochód ${reason || ""}. Zdjęci${
|
||||
photos.length === 1 ? "e" : "a"
|
||||
} wykonane ${date_str} o godz. ${hour} w pobliżu ul. ${
|
||||
location.address
|
||||
}. Wnoszę o ukaranie.
|
||||
`;
|
||||
|
||||
const main_data = {
|
||||
...minimal_data,
|
||||
srs: "EPSG:2177",
|
||||
uz_process_personal_data_agreement: "Y",
|
||||
uz_kategoria: 86808,
|
||||
uz_temat: subject,
|
||||
uz_tresc: body,
|
||||
uz_email: contact_details.email,
|
||||
uz_odpowiedz: "tak",
|
||||
uz_imie_nazwisko: contact_details.imie_nazwisko,
|
||||
uz_adres: contact_details.adres,
|
||||
};
|
||||
|
||||
const forms = [
|
||||
{
|
||||
...main_data,
|
||||
source: "sm_zgloszenia_step1",
|
||||
goto_sm_zgloszenia_step1_1: "",
|
||||
},
|
||||
{
|
||||
source: "sm_zgloszenia_step1_1",
|
||||
x,
|
||||
y,
|
||||
lon: x,
|
||||
lat: y,
|
||||
srs: "EPSG:2177",
|
||||
id_ulica_city: "Poznań",
|
||||
srs_id: "EPSG:2177",
|
||||
id_ulica_street_lookup: "Limanowskiego",
|
||||
goto_sm_zgloszenia_step1: "",
|
||||
},
|
||||
{ ...main_data, goto_sm_zgloszenia_step1_2: "" },
|
||||
...photos.map((file_path) => ({
|
||||
...minimal_data,
|
||||
source: "sm_zgloszenia_step1_2",
|
||||
goto_sm_zgloszenia_step1_2: "",
|
||||
uz_file: {
|
||||
path: file_path,
|
||||
filename: "photo1.jpg",
|
||||
contentType: "image/jpeg",
|
||||
},
|
||||
})),
|
||||
{
|
||||
...minimal_data,
|
||||
source: "sm_zgloszenia_step1_2",
|
||||
goto_sm_zgloszenia_step1: "",
|
||||
},
|
||||
{ ...main_data, source: "sm_zgloszenia_step1", goto_summary: "" },
|
||||
];
|
||||
|
||||
for (let form of forms) {
|
||||
const formData = new FormData();
|
||||
for (let [key, value] of Object.entries(form)) {
|
||||
if (value.path) {
|
||||
formData.append(key, fs.createReadStream(value.path), {
|
||||
filename: value.filename,
|
||||
contentType: value.contentType,
|
||||
});
|
||||
} else {
|
||||
formData.append(key, value);
|
||||
}
|
||||
}
|
||||
const response = await transport.post(SM_URL, formData, {
|
||||
headers: { ...headers, ...formData.getHeaders() },
|
||||
jar,
|
||||
});
|
||||
console.log(response.request._headers);
|
||||
}
|
||||
const session_id = (jar as any).store.idx["www.um.poznan.pl"]["/mim"]
|
||||
.JSESSIONID.value;
|
||||
|
||||
const response = await spawn("curl", [
|
||||
"https://www.um.poznan.pl/mim/forms/sm_zgloszenia.html?instance=poznan_sm",
|
||||
"-H",
|
||||
`User-Agent: ${headers["User-Agent"]}`,
|
||||
"-H",
|
||||
`Accept: ${headers.Accept}`,
|
||||
"-H",
|
||||
"Accept-Language: en-US,en;q=0.5",
|
||||
"--compressed",
|
||||
"-H",
|
||||
"Content-Type: application/x-www-form-urlencoded",
|
||||
"-H",
|
||||
`Origin: ${headers.Origin}`,
|
||||
"-H",
|
||||
"DNT: 1",
|
||||
"-H",
|
||||
"Connection: keep-alive",
|
||||
"-H",
|
||||
`Referer: ${headers.Referer}`,
|
||||
"-H",
|
||||
`Cookie: mim_cookie_test=enabled; JSESSIONID=${session_id}`,
|
||||
"-H",
|
||||
"Upgrade-Insecure-Requests: 1",
|
||||
"--data",
|
||||
`action=save&source=summary&instance=poznan_sm&x=${x}&y=${y}&lon=${x}&lat=${y}&srs=EPSG%3A2177&goto_thanks=`,
|
||||
]);
|
||||
console.log(response);
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
import transformation from "transform-coordinates";
|
||||
|
||||
export type Coordinates = {
|
||||
lat: number;
|
||||
lon: number;
|
||||
};
|
||||
|
||||
export type CityCoordinates = {
|
||||
x: number;
|
||||
y: number;
|
||||
z: number;
|
||||
};
|
||||
|
||||
export interface LocationData {
|
||||
coordinates: Coordinates;
|
||||
address: string;
|
||||
}
|
||||
|
||||
export function toCityCoordinates(coords: Coordinates): CityCoordinates {
|
||||
const transform = transformation("EPSG:4326", "EPSG:2177");
|
||||
const city_coordinates = transform.forward({
|
||||
x: coords.lon,
|
||||
y: coords.lat,
|
||||
});
|
||||
return city_coordinates;
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
const months = [
|
||||
"stycznia",
|
||||
"lutego",
|
||||
"marca",
|
||||
"kwietnia",
|
||||
"maja",
|
||||
"czerwca",
|
||||
"lipca",
|
||||
"sierpnia",
|
||||
"września",
|
||||
"października",
|
||||
"listopada",
|
||||
"grudnia",
|
||||
];
|
||||
|
||||
export default months;
|
@ -0,0 +1,11 @@
|
||||
declare module "transform-coordinates" {
|
||||
export default function getTransport(
|
||||
coords1: string,
|
||||
coords2: string
|
||||
): {
|
||||
forward: (coords: {
|
||||
x: number;
|
||||
y: number;
|
||||
}) => { x: number; y: number; z: number };
|
||||
};
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"noImplicitAny": true,
|
||||
"noImplicitThis": true,
|
||||
"strictNullChecks": true,
|
||||
"target": "ES2020",
|
||||
"declaration": true,
|
||||
"esModuleInterop": true,
|
||||
"lib": ["es6", "esnext"],
|
||||
"outDir": "lib",
|
||||
"checkJs": true,
|
||||
"allowJs": true,
|
||||
"declarationDir": "@types",
|
||||
"sourceMap": true
|
||||
},
|
||||
"include": ["src/**/*"]
|
||||
}
|
Loading…
Reference in New Issue