|
@@ -18,7 +18,7 @@ import { SocksProxyAgent } from 'socks-proxy-agent';
|
|
|
|
|
|
import { getLogger } from './loggers';
|
|
|
import QQBot from './koishi';
|
|
|
-import { BigNumOps } from './utils';
|
|
|
+import { Arr, BigNumOps, chainPromises } from './utils';
|
|
|
import Webshot, { Cookies, Page } from './webshot';
|
|
|
|
|
|
const parseLink = (link: string): { userName?: string, postUrlSegment?: string } => {
|
|
@@ -418,7 +418,7 @@ export default class {
|
|
|
));
|
|
|
}).finally(() => { page.close(); });
|
|
|
});
|
|
|
- setTimeout(this.work, this.workInterval * 1000);
|
|
|
+ setTimeout(this.work, this.workInterval * 1000 / this.lock.feed.length);
|
|
|
}
|
|
|
);
|
|
|
};
|
|
@@ -479,52 +479,57 @@ export default class {
|
|
|
setTimeout(this.work, this.workInterval * 1000);
|
|
|
return;
|
|
|
}
|
|
|
- if (lock.workon >= lock.feed.length) lock.workon = 0;
|
|
|
- if (!lock.threads[lock.feed[lock.workon]] ||
|
|
|
- !lock.threads[lock.feed[lock.workon]].subscribers ||
|
|
|
- lock.threads[lock.feed[lock.workon]].subscribers.length === 0) {
|
|
|
- logger.warn(`nobody subscribes thread ${lock.feed[lock.workon]}, removing from feed`);
|
|
|
- delete lock.threads[lock.feed[lock.workon]];
|
|
|
- lock.feed.splice(lock.workon, 1);
|
|
|
+ lock.feed.forEach((feed, index) => {
|
|
|
+ if (!lock.threads[feed] ||
|
|
|
+ !lock.threads[feed].subscribers ||
|
|
|
+ lock.threads[feed].subscribers.length === 0) {
|
|
|
+ logger.warn(`nobody subscribes thread ${feed}, removing from feed`);
|
|
|
+ delete lock.threads[index];
|
|
|
+ lock.feed.splice(index, 1);
|
|
|
+ fs.writeFileSync(path.resolve(this.lockfile), JSON.stringify(lock));
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ chainPromises(Arr.chunk(lock.feed, 5).map((arr, i) => () => Promise.all(arr.map((currentFeed, j) => {
|
|
|
+ lock.workon = i * 5 + j;
|
|
|
fs.writeFileSync(path.resolve(this.lockfile), JSON.stringify(lock));
|
|
|
- this.work();
|
|
|
- return;
|
|
|
- }
|
|
|
|
|
|
- const currentFeed = lock.feed[lock.workon];
|
|
|
+ const promiseDelay = this.workInterval * (Math.random() + j) * 500 / lock.feed.length;
|
|
|
+ logger.debug(`timeout for this pull job: ${promiseDelay * 2}`);
|
|
|
|
|
|
- const promise = new Promise<LazyMediaItem[]>(resolve => {
|
|
|
- const match = /https:\/\/www\.instagram\.com\/([^\/]+)/.exec(currentFeed);
|
|
|
- if (!match) {
|
|
|
- logger.error(`current feed "${currentFeed}" is invalid, please remove this feed manually`);
|
|
|
- return resolve([]);
|
|
|
- }
|
|
|
- this.queryUserMedia(match[1], this.lock.threads[currentFeed].offset)
|
|
|
- .then(resolve)
|
|
|
- .catch((error: Error) => {
|
|
|
- logger.error(`error scraping media off profile page of ${match[1]}, error: ${error}`);
|
|
|
- resolve([]);
|
|
|
- });
|
|
|
- });
|
|
|
+ const promise = promisify(setTimeout)(promiseDelay).then(() => {
|
|
|
+ const match = /https:\/\/www\.instagram\.com\/([^\/]+)/.exec(currentFeed);
|
|
|
+ if (!match) {
|
|
|
+ logger.error(`current feed "${currentFeed}" is invalid, please remove this feed manually`);
|
|
|
+ return [] as LazyMediaItem[];
|
|
|
+ }
|
|
|
+ return this.queryUserMedia(match[1], this.lock.threads[currentFeed].offset)
|
|
|
+ .catch((error: Error) => {
|
|
|
+ logger.error(`error scraping media off profile page of ${match[1]}, error: ${error}`);
|
|
|
+ return [] as LazyMediaItem[];
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ promise.then((mediaItems: LazyMediaItem[]) => {
|
|
|
+ const currentThread = lock.threads[currentFeed];
|
|
|
|
|
|
- promise.then((mediaItems: LazyMediaItem[]) => {
|
|
|
- const currentThread = lock.threads[currentFeed];
|
|
|
+ const updateDate = () => currentThread.updatedAt = new Date().toString();
|
|
|
+ if (!mediaItems || mediaItems.length === 0) { updateDate(); return; }
|
|
|
|
|
|
- const updateDate = () => currentThread.updatedAt = new Date().toString();
|
|
|
- if (!mediaItems || mediaItems.length === 0) { updateDate(); return; }
|
|
|
+ const topOfFeed = mediaItems[0].pk;
|
|
|
+ const updateOffset = () => currentThread.offset = topOfFeed;
|
|
|
|
|
|
- const topOfFeed = mediaItems[0].pk;
|
|
|
- const updateOffset = () => currentThread.offset = topOfFeed;
|
|
|
+ if (currentThread.offset === '-1') { updateOffset(); return; }
|
|
|
+ if (currentThread.offset === '0') mediaItems.splice(1);
|
|
|
|
|
|
- if (currentThread.offset === '-1') { updateOffset(); return; }
|
|
|
- if (currentThread.offset === '0') mediaItems.splice(1);
|
|
|
+ return this.workOnMedia(mediaItems, this.sendMedia(`thread ${currentFeed}`, ...currentThread.subscribers))
|
|
|
+ .then(updateDate).then(updateOffset);
|
|
|
+ }).then(() => fs.writeFileSync(path.resolve(this.lockfile), JSON.stringify(lock)));
|
|
|
|
|
|
- return this.workOnMedia(mediaItems, this.sendMedia(`thread ${currentFeed}`, ...currentThread.subscribers))
|
|
|
- .then(updateDate).then(updateOffset);
|
|
|
- })
|
|
|
+ return promisify(setTimeout)(promiseDelay * 3);
|
|
|
+ }))))
|
|
|
.then(() => {
|
|
|
- lock.workon++;
|
|
|
- let timeout = this.workInterval * 1000 / lock.feed.length;
|
|
|
+ let timeout = this.workInterval * 500;
|
|
|
if (timeout < 1000) timeout = 1000;
|
|
|
fs.writeFileSync(path.resolve(this.lockfile), JSON.stringify(lock));
|
|
|
setTimeout(() => {
|