|
@@ -16,14 +16,14 @@ import QQBot, { Message } from './koishi';
|
|
|
import { BigNumOps } from './utils';
|
|
|
import Webshot, { Cookies, Page } from './webshot';
|
|
|
|
|
|
-const parseLink = (link: string): {userName?: string, postUrlSegment?: string} => {
|
|
|
+const parseLink = (link: string): { userName?: string, postUrlSegment?: string } => {
|
|
|
let match =
|
|
|
/instagram\.com\/p\/([A-Za-z0-9\-_]+)/.exec(link);
|
|
|
- if (match) return {postUrlSegment: match[1]};
|
|
|
+ if (match) return { postUrlSegment: match[1] };
|
|
|
match =
|
|
|
/instagram\.com\/([^\/?#]+)/.exec(link) ||
|
|
|
/^([^\/?#]+)$/.exec(link);
|
|
|
- if (match) return {userName: ScreenNameNormalizer.normalize(match[1]).split(':')[0]};
|
|
|
+ if (match) return { userName: ScreenNameNormalizer.normalize(match[1]).split(':')[0] };
|
|
|
return;
|
|
|
};
|
|
|
|
|
@@ -34,7 +34,7 @@ const linkBuilder = (config: ReturnType<typeof parseLink>): string => {
|
|
|
if (config.postUrlSegment) return `https://www.instagram.com/p/${config.postUrlSegment}/`;
|
|
|
};
|
|
|
|
|
|
-export {linkBuilder, parseLink, isValidUrlSegment, idToUrlSegment, urlSegmentToId};
|
|
|
+export { linkBuilder, parseLink, isValidUrlSegment, idToUrlSegment, urlSegmentToId };
|
|
|
|
|
|
interface IWorkerOption {
|
|
|
sessionLockfile: string;
|
|
@@ -55,7 +55,7 @@ export class SessionManager {
|
|
|
private username: string;
|
|
|
private password: string;
|
|
|
private lockfile: string;
|
|
|
-
|
|
|
+
|
|
|
constructor(client: IgApiClient, file: string, credentials: [string, string]) {
|
|
|
this.ig = client;
|
|
|
this.lockfile = file;
|
|
@@ -68,8 +68,8 @@ export class SessionManager {
|
|
|
const filePath = path.resolve(this.lockfile);
|
|
|
if (fs.existsSync(filePath)) {
|
|
|
try {
|
|
|
- const serialized = JSON.parse(fs.readFileSync(filePath, 'utf8')) as {[key: string]: any};
|
|
|
- return this.ig.state.deserialize(serialized).then(() => {
|
|
|
+ const serialized = JSON.parse(fs.readFileSync(filePath, 'utf8')) as { [key: string]: any };
|
|
|
+ return this.ig.state.deserialize(serialized).then(() => {
|
|
|
logger.info(`successfully loaded client session cookies for user ${this.username}`);
|
|
|
});
|
|
|
} catch (err) {
|
|
@@ -89,7 +89,7 @@ export class SessionManager {
|
|
|
|
|
|
public save = () =>
|
|
|
this.ig.state.serialize()
|
|
|
- .then((serialized: {[key: string]: any}) => {
|
|
|
+ .then((serialized: { [key: string]: any }) => {
|
|
|
delete serialized.constants;
|
|
|
return fs.writeFileSync(path.resolve(this.lockfile), JSON.stringify(serialized, null, 2), 'utf-8');
|
|
|
});
|
|
@@ -122,7 +122,7 @@ let browserLogin = (page: Page): Promise<void> => Promise.reject();
|
|
|
let browserSaveCookies = browserLogin;
|
|
|
|
|
|
const acceptCookieConsent = (page: Page) =>
|
|
|
- page.click('button:has-text("すべて許可")', {timeout: 5000})
|
|
|
+ page.click('button:has-text("すべて許可")', { timeout: 5000 })
|
|
|
.then(() => logger.info('accepted cookie consent'))
|
|
|
.catch((err: Error) => { if (err.name !== 'TimeoutError') throw err; });
|
|
|
|
|
@@ -243,7 +243,7 @@ export default class {
|
|
|
});
|
|
|
WebshotHelpers.handleLogin = page =>
|
|
|
browserLogin(page)
|
|
|
- .then(() => page.waitForSelector('img[data-testid="user-avatar"]', {timeout: this.webshotDelay}))
|
|
|
+ .then(() => page.waitForSelector('img[data-testid="user-avatar"]', { timeout: this.webshotDelay }))
|
|
|
.then(() => browserSaveCookies(page))
|
|
|
.catch((err: Error) => {
|
|
|
if (err.name === 'TimeoutError') logger.warn('navigation timed out, assuming login has failed');
|
|
@@ -257,7 +257,7 @@ export default class {
|
|
|
}
|
|
|
return '找不到请求的媒体,它可能已被删除。';
|
|
|
};
|
|
|
- getPostOwner = (segmentId) =>
|
|
|
+ getPostOwner = (segmentId) =>
|
|
|
this.client.media.info(urlSegmentToId(segmentId))
|
|
|
.then(media => media.items[0].user)
|
|
|
.then(user => `${user.username}:${user.pk}`)
|
|
@@ -276,7 +276,7 @@ export default class {
|
|
|
doOnNewPage => {
|
|
|
this.queryUserMedia = ((userName, targetId) => {
|
|
|
let page: Page;
|
|
|
- const url = linkBuilder({userName});
|
|
|
+ const url = linkBuilder({ userName });
|
|
|
logger.debug(`pulling ${targetId !== '0' ? `feed ${url} up to ${targetId}` : `top of feed ${url}`}...`);
|
|
|
return doOnNewPage(newPage => {
|
|
|
page = newPage;
|
|
@@ -285,7 +285,7 @@ export default class {
|
|
|
const getTimerTime = () => new Date().getTime() - startTime;
|
|
|
const getTimeout = () => Math.max(500, timeout - getTimerTime());
|
|
|
return page.context().addCookies(this.webshotCookies)
|
|
|
- .then(() => page.goto(url, {waitUntil: 'load', timeout: getTimeout()}))
|
|
|
+ .then(() => page.goto(url, { waitUntil: 'load', timeout: getTimeout() }))
|
|
|
.then(response => {
|
|
|
if (response.status() !== 200) {
|
|
|
const err = new Error(
|
|
@@ -296,7 +296,7 @@ export default class {
|
|
|
});
|
|
|
}
|
|
|
}).then(() => acceptCookieConsent(page))
|
|
|
- .then(() =>
|
|
|
+ .then(() =>
|
|
|
(next => Promise.race([
|
|
|
browserLogin(page)
|
|
|
.catch((err: Error) => {
|
|
@@ -306,14 +306,14 @@ export default class {
|
|
|
.then(() => browserSaveCookies(page))
|
|
|
.then(() => page.goto(url)).then(next),
|
|
|
next(),
|
|
|
- ]))(() => page.waitForSelector('article', {timeout: getTimeout()}))
|
|
|
+ ]))(() => page.waitForSelector('article', { timeout: getTimeout() }))
|
|
|
).then(handle => {
|
|
|
const postHandler = () => {
|
|
|
- const toId = (href: string) => urlSegmentToId((/\/p\/(.*)\/$/.exec(href) ?? [])[1]);
|
|
|
+ const toId = (href: string) => urlSegmentToId((/\/p\/(.*)\/$/.exec(href) ?? [,''])[1]);
|
|
|
if (targetId === '0') {
|
|
|
return handle.$$eval('a', as =>
|
|
|
as.filter(a => !a.querySelector('[aria-label="IGTV"]'))[0].href
|
|
|
- ).then(href => href ? [toId(href)] : null);
|
|
|
+ ).then(href => Number(toId(href)) > 0 ? [toId(href)] : []);
|
|
|
}
|
|
|
return handle.$$eval('a', as =>
|
|
|
as.filter(a => !a.querySelector('[aria-label="IGTV"]')).map(a => a.href)
|
|
@@ -387,7 +387,7 @@ export default class {
|
|
|
logger.warn(`retry sending to ${subscriber.chatID} for the ${ordinal(count)} time...`);
|
|
|
} else {
|
|
|
logger.warn(`${count - 1} consecutive failures while sending` +
|
|
|
- 'message chain, trying plain text instead...');
|
|
|
+ 'message chain, trying plain text instead...');
|
|
|
terminate(this.bot.sendTo(subscriber, author + text));
|
|
|
}
|
|
|
});
|