+4
-4
@@ -94,4 +94,4 @@ #!/usr/bin/env node | ||
| newPosts | ||
| .filter(p => p.number <= 1000) | ||
| .forEach(post => { | ||
| .filter((p) => p.number <= 1000) | ||
| .forEach((post) => { | ||
| console.log(`${post.number}:${post.userId.substr(0, 3)}: ${post.message}`); | ||
@@ -114,3 +114,3 @@ }); | ||
| case "dump": | ||
| dump_1.getThread(cli.input[1]).then(ress => { | ||
| dump_1.getThread(cli.input[1]).then((ress) => { | ||
| console.log(JSON.stringify(ress, null, "\t")); | ||
@@ -120,3 +120,3 @@ }); | ||
| case "dump-threads": | ||
| dump_1.getThreads().then(res => { | ||
| dump_1.getThreads(cli.input[1]).then((res) => { | ||
| console.log(JSON.stringify(res, null, "\t")); | ||
@@ -123,0 +123,0 @@ }); |
+1
-1
| import { Thread, ThreadMin } from "./types"; | ||
| export declare const client: import("axios").AxiosInstance; | ||
| export declare function getThreads(): Promise<{ | ||
| export declare function getThreads(url: any): Promise<{ | ||
| threads: ThreadMin[]; | ||
@@ -5,0 +5,0 @@ }>; |
+27
-29
@@ -6,2 +6,3 @@ "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| exports.postMessage = exports.getThread = exports.getThreadVip = exports.getThreadPart4Vip = exports.getThreads = exports.client = void 0; | ||
| const cheerio_1 = __importDefault(require("cheerio")); | ||
@@ -13,6 +14,6 @@ const axios_1 = __importDefault(require("axios")); | ||
| const host = "http://hebi.5ch.net"; | ||
| const makeThreadUrl = id => `${host}/test/read.cgi/news4vip/${id}`; | ||
| const makeThreadUrl = (id) => `${host}/test/read.cgi/news4vip/${id}`; | ||
| const listPageUrl = `${host}/news4vip/subback.html`; | ||
| axios_1.default.defaults.responseType = "arraybuffer"; | ||
| axios_1.default.defaults.transformResponse = data => encoding_japanese_1.default.convert(data, { to: "UNICODE", from: "SJIS", type: "string" }); | ||
| axios_1.default.defaults.transformResponse = (data) => encoding_japanese_1.default.convert(data, { to: "UNICODE", from: "SJIS", type: "string" }); | ||
| exports.client = axios_1.default.create({ withCredentials: true }); | ||
@@ -38,7 +39,7 @@ const sizeRegex = /\d+KB/; | ||
| }; | ||
| async function getThreads() { | ||
| const res = await exports.client.get(listPageUrl); | ||
| async function getThreads(url) { | ||
| const res = await exports.client.get(url || listPageUrl); | ||
| const $ = cheerio_1.default.load(res.data); | ||
| const threads = []; | ||
| $("#trad > a").map((i, elA) => { | ||
| $("#trad > a").each((i, elA) => { | ||
| const a = $(elA); | ||
@@ -51,2 +52,4 @@ const res = titleParse(a.text()); | ||
| const href = a.attr("href"); | ||
| if (!href) | ||
| throw new Error("parse html error"); | ||
| const id = href.split("/")[0]; | ||
@@ -61,9 +64,7 @@ const url = makeThreadUrl(id); | ||
| const $ = cheerio_1.default.load((await exports.client.get(`${url}${from}-`)).data); | ||
| const title = $("h1") | ||
| .text() | ||
| .trim(); | ||
| const title = $("h1").text().trim(); | ||
| const size = $("font > b").text(); | ||
| const posts = []; | ||
| // console.log(_.zip($("dl > dt"), $("dl > dd"))) | ||
| lodash_1.default.zip($("dl > dt"), $("dl > dd")).map(([dt, dd], i) => { | ||
| lodash_1.default.zip($("dl > dt"), $("dl > dd")).forEach(([dt, dd], i) => { | ||
| if (!dd || !dt) { | ||
@@ -94,27 +95,22 @@ return; | ||
| const $ = cheerio_1.default.load((await exports.client.get(`${url}${from}-`)).data); | ||
| const title = $(".title") | ||
| .text() | ||
| .trim(); | ||
| const title = $(".title").text().trim(); | ||
| const m = sizeRegex.exec($(".metastats.meta.centered").text()); | ||
| const size = m ? m[0] : ""; | ||
| const posts = []; | ||
| $(".post").map((i, elA) => { | ||
| $(".post").each((i, elA) => { | ||
| const div = $(elA); | ||
| const number = Number(div.find(".number").text()); | ||
| const name = toName(div.find(".name").text()); | ||
| const userId = div | ||
| .find(".uid") | ||
| .text() | ||
| .split(":")[1]; | ||
| const userId = div.find(".uid").text().split(":")[1]; | ||
| const dateStr = div.find(".date").text(); | ||
| const timestamp = util_1.dateParse(dateStr); | ||
| const comma = Number(dateStr.split(".")[1]); | ||
| const message = div | ||
| .find(".message") | ||
| .text() | ||
| .trim(); | ||
| const message = div.find(".message").text().trim(); | ||
| const img = div.find(".message img").eq(0); | ||
| const images = util_1.getImgUrls(message); | ||
| if (img.length > 0) { | ||
| images.push(img.attr("src")); | ||
| const imgurl = img.attr("src"); | ||
| if (imgurl) { | ||
| images.push(imgurl); | ||
| } | ||
| } | ||
@@ -157,3 +153,3 @@ posts.push({ | ||
| } | ||
| return headers["set-cookie"].map(v => v.split(";")[0]); | ||
| return headers["set-cookie"].map((v) => v.split(";")[0]); | ||
| }; | ||
@@ -172,5 +168,5 @@ async function postMessage(url, message) { | ||
| const headers = { | ||
| accept: "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3", | ||
| accept: "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", | ||
| "accept-encoding": "gzip, deflate, br", | ||
| "accept-language": "ja,en-US;q=0.9,en;q=0.8,es;q=0.7", | ||
| "accept-language": "ja,en-US;q=0.9,en;q=0.8", | ||
| "cache-control": "max-age=0", | ||
@@ -181,6 +177,7 @@ "content-type": "application/x-www-form-urlencoded", | ||
| "sec-fetch-mode": "navigate", | ||
| "sec-fetch-site": "same-origin", | ||
| "sec-fetch-site": "cross-site", | ||
| "sec-fetch-dest": "document", | ||
| "sec-fetch-user": "?1", | ||
| "upgrade-insecure-requests": "1", | ||
| "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11", | ||
| "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 OPR/73.0.3856.284", | ||
| cookie: cookies.join("; "), | ||
@@ -201,6 +198,7 @@ }; | ||
| const form = generateForm(makeForm); | ||
| const post = headers => exports.client.post(bbsUrl, form, { headers }); | ||
| const post = (headers) => exports.client.post(bbsUrl, form, { headers }); | ||
| const res = await post(headers); | ||
| console.log(res.data); | ||
| if (res.data && res.data.includes("書き込み確認")) { | ||
| parseSetCookies(res.headers).forEach(s => cookies.push(s)); | ||
| parseSetCookies(res.headers).forEach((s) => cookies.push(s)); | ||
| headers.cookie = cookies.join("; "); | ||
@@ -207,0 +205,0 @@ await post(headers); |
+1
-1
@@ -10,3 +10,3 @@ import hosyu from "./hosyu"; | ||
| }; | ||
| watchSmart: (threadURL: string, crawledCallback?: import("./types").CrawledCallback) => { | ||
| watchSmart: (threadURL: string, crawledCallback: import("./types").CrawledCallback) => { | ||
| start: () => Promise<void>; | ||
@@ -13,0 +13,0 @@ restart: () => Promise<void>; |
+1
-1
@@ -9,3 +9,3 @@ "use strict"; | ||
| const util_1 = require("./util"); | ||
| const sleep = (msec) => new Promise(resolve => setTimeout(resolve, msec)); | ||
| const sleep = (msec) => new Promise((resolve) => setTimeout(resolve, msec)); | ||
| // ◆のマッチに適用する | ||
@@ -12,0 +12,0 @@ function regexPatch(str) { |
@@ -1,2 +0,2 @@ | ||
| /// <reference types="node" /> | ||
| declare type Timeout = ReturnType<typeof setTimeout>; | ||
| export declare type Wacchoi = { | ||
@@ -44,4 +44,5 @@ raw: string; | ||
| nextCallMs: number; | ||
| timeout: NodeJS.Timeout | null; | ||
| timeout: Timeout | null; | ||
| finish: boolean; | ||
| }) => void; | ||
| export {}; |
+1
-1
@@ -7,3 +7,3 @@ import { Wacchoi } from "./types"; | ||
| export declare const dateParse: (str: string) => number; | ||
| export declare const parseWacchoi: (name: string) => [false | Wacchoi, string]; | ||
| export declare const parseWacchoi: (name: string) => [Wacchoi | false, string]; | ||
| export declare function getImgUrls(text: string): string[]; |
+11
-6
@@ -6,2 +6,3 @@ "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| exports.getImgUrls = exports.parseWacchoi = exports.dateParse = exports.easyRegex = exports.normalizeUrl = exports.increment = exports.hosyuIntervalTimeMinute = void 0; | ||
| const lodash_1 = __importDefault(require("lodash")); | ||
@@ -47,5 +48,5 @@ function hosyuIntervalTimeMinute(hour, holiday = false) { | ||
| function* increment(start = "a") { | ||
| const nexts = start.split("").map(v => chars.indexOf(v)); | ||
| const nexts = start.split("").map((v) => chars.indexOf(v)); | ||
| while (true) { | ||
| const r = lodash_1.default.reverse(nexts.map(i => chars[i])).join(""); | ||
| const r = lodash_1.default.reverse(nexts.map((i) => chars[i])).join(""); | ||
| const noUp = nexts.find((v, i) => { | ||
@@ -67,6 +68,8 @@ const nv = v + 1; | ||
| exports.increment = increment; | ||
| exports.normalizeUrl = (url) => url + (url.endsWith("/") ? "" : "/"); | ||
| exports.easyRegex = (pattern) => pattern.replace(/%d/g, "(\\d+)").replace(/%s/g, "(.+)"); | ||
| const normalizeUrl = (url) => url + (url.endsWith("/") ? "" : "/"); | ||
| exports.normalizeUrl = normalizeUrl; | ||
| const easyRegex = (pattern) => pattern.replace(/%d/g, "(\\d+)").replace(/%s/g, "(.+)"); | ||
| exports.easyRegex = easyRegex; | ||
| // 2019/10/26(土) 00:00:07.589 | ||
| exports.dateParse = (str) => { | ||
| const dateParse = (str) => { | ||
| const er = exports.easyRegex("%d/%d/%d\\(.+\\) %d:%d:%d\\.%d"); | ||
@@ -82,4 +85,5 @@ const m = new RegExp(er).exec(str); | ||
| }; | ||
| exports.dateParse = dateParse; | ||
| // 以下、5ちゃんねるからVIPがお送りします (ワッチョイWW 8f70-cmdO) | ||
| exports.parseWacchoi = (name) => { | ||
| const parseWacchoi = (name) => { | ||
| const m = /(.*) (\((.*) ((..)(..)-(....))\))/.exec(name); | ||
@@ -92,2 +96,3 @@ if (!m) { | ||
| }; | ||
| exports.parseWacchoi = parseWacchoi; | ||
| function getImgUrls(text) { | ||
@@ -94,0 +99,0 @@ const rex = /(https?:\/\/.*?\.(?:png|jpg|gif))/g; |
+1
-1
| import { CrawledCallback } from "./types"; | ||
| export declare const nextTime: (num: number) => number; | ||
| export declare const watchSmart: (threadURL: string, crawledCallback?: CrawledCallback) => { | ||
| export declare const watchSmart: (threadURL: string, crawledCallback: CrawledCallback) => { | ||
| start: () => Promise<void>; | ||
@@ -5,0 +5,0 @@ restart: () => Promise<void>; |
+12
-6
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| exports.watch = exports.watchSmart = exports.nextTime = void 0; | ||
| const dump_1 = require("./dump"); | ||
| const min10 = 10 * 60 * 1000; | ||
| const recentPostCount = (posts) => posts.filter(post => post.timestamp >= +Date.now() - min10).length; | ||
| function watcher(threadURL, crawledCallback = () => { }, crawlTimeFunc) { | ||
| const recentPostCount = (posts) => posts.filter((post) => post.timestamp >= +Date.now() - min10).length; | ||
| function watcher(threadURL, crawledCallback, crawlTimeFunc) { | ||
| const readed = {}; | ||
@@ -23,3 +24,3 @@ const memo = { nthCall: 0, next: 1, timeout: null }; | ||
| const newPosts = thread.posts; | ||
| newPosts.forEach(post => { | ||
| newPosts.forEach((post) => { | ||
| readed[post.number] = post; | ||
@@ -48,4 +49,9 @@ }); | ||
| } | ||
| exports.nextTime = (num) => Math.min(min10 / (num + 1), 60000); | ||
| exports.watchSmart = (threadURL, crawledCallback = () => { }) => watcher(threadURL, crawledCallback, exports.nextTime); | ||
| exports.watch = (threadURL, crawledCallback = () => { }, intervalMs = 1 * 60 * 1000) => watcher(threadURL, crawledCallback, () => intervalMs); | ||
| const nextTime = (num) => Math.min(min10 / (num + 1), 60000); | ||
| exports.nextTime = nextTime; | ||
| const watchSmart = (threadURL, crawledCallback) => watcher(threadURL, crawledCallback, exports.nextTime); | ||
| exports.watchSmart = watchSmart; | ||
| const watch = (threadURL, crawledCallback = () => { | ||
| // default empty | ||
| }, intervalMs = 1 * 60 * 1000) => watcher(threadURL, crawledCallback, () => intervalMs); | ||
| exports.watch = watch; |
+1
-1
| { | ||
| "name": "chch", | ||
| "version": "2.4.1", | ||
| "version": "2.4.2", | ||
| "author": "vipzero", | ||
@@ -5,0 +5,0 @@ "repository": "vipzero/chch", |
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
29621
2.79%685
1.48%5
25%