Chrunos commited on
Commit
35cd637
·
verified ·
1 Parent(s): e314e2e

Update api/src/processing/cookie/manager.js

Browse files
Files changed (1) hide show
  1. api/src/processing/cookie/manager.js +121 -30
api/src/processing/cookie/manager.js CHANGED
@@ -1,50 +1,145 @@
1
  import Cookie from './cookie.js';
 
2
  import { readFile, writeFile } from 'fs/promises';
 
3
  import { parse as parseSetCookie, splitCookiesString } from 'set-cookie-parser';
4
- import { env } from '../../config.js';
 
5
 
6
- const WRITE_INTERVAL = 60000,
7
- cookiePath = env.cookiePath,
8
- COUNTER = Symbol('counter');
 
 
 
 
 
 
9
 
 
10
  let cookies = {}, dirty = false, intervalId;
11
 
12
- const setup = async () => {
13
- try {
14
- if (!cookiePath) return;
 
 
 
 
 
 
 
 
 
15
 
 
 
16
  cookies = await readFile(cookiePath, 'utf8');
17
  cookies = JSON.parse(cookies);
18
- intervalId = setInterval(writeChanges, WRITE_INTERVAL)
19
- } catch { /* no cookies for you */ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  }
21
 
22
- setup();
 
 
 
 
 
 
 
 
 
23
 
24
- function writeChanges() {
25
- if (!dirty) return;
26
  dirty = false;
 
27
 
28
- writeFile(cookiePath, JSON.stringify(cookies, null, 4)).catch(() => {
29
- clearInterval(intervalId)
30
- })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  }
32
 
33
  export function getCookie(service) {
 
 
 
 
 
 
 
 
34
  if (!cookies[service] || !cookies[service].length) return;
35
 
36
- let n;
37
- if (cookies[service][COUNTER] === undefined) {
38
- n = cookies[service][COUNTER] = 0
39
- } else {
40
- ++cookies[service][COUNTER]
41
- n = (cookies[service][COUNTER] %= cookies[service].length)
42
  }
43
 
44
- const cookie = cookies[service][n];
45
- if (typeof cookie === 'string') cookies[service][n] = Cookie.fromString(cookie);
 
 
 
 
46
 
47
- return cookies[service][n]
 
 
 
 
 
 
 
 
 
 
 
 
48
  }
49
 
50
  export function updateCookie(cookie, headers) {
@@ -57,10 +152,6 @@ export function updateCookie(cookie, headers) {
57
 
58
  cookie.unset(parsed.filter(c => c.expires < new Date()).map(c => c.name));
59
  parsed.filter(c => !c.expires || c.expires > new Date()).forEach(c => values[c.name] = c.value);
60
- updateCookieValues(cookie, values);
61
- }
62
 
63
- export function updateCookieValues(cookie, values) {
64
- cookie.set(values);
65
- if (Object.keys(values).length) dirty = true
66
- }
 
1
  import Cookie from './cookie.js';
2
+
3
  import { readFile, writeFile } from 'fs/promises';
4
+ import { Red, Green, Yellow } from '../../misc/console-text.js';
5
  import { parse as parseSetCookie, splitCookiesString } from 'set-cookie-parser';
6
+ import * as cluster from '../../misc/cluster.js';
7
+ import { isCluster } from '../../config.js';
8
 
9
+ const WRITE_INTERVAL = 60000;
10
+ const VALID_SERVICES = new Set([
11
+ 'instagram',
12
+ 'instagram_bearer',
13
+ 'reddit',
14
+ 'twitter',
15
+ 'youtube',
16
+ 'youtube_oauth'
17
+ ]);
18
 
19
+ const invalidCookies = {};
20
  let cookies = {}, dirty = false, intervalId;
21
 
22
+ function writeChanges(cookiePath) {
23
+ if (!dirty) return;
24
+ dirty = false;
25
+
26
+ const cookieData = JSON.stringify({ ...cookies, ...invalidCookies }, null, 4);
27
+ writeFile(cookiePath, cookieData).catch((e) => {
28
+ console.warn(`${Yellow('[!]')} failed writing updated cookies to storage`);
29
+ console.warn(e);
30
+ clearInterval(intervalId);
31
+ intervalId = null;
32
+ })
33
+ }
34
 
35
+ const setupMain = async (cookiePath) => {
36
+ try {
37
  cookies = await readFile(cookiePath, 'utf8');
38
  cookies = JSON.parse(cookies);
39
+ for (const serviceName in cookies) {
40
+ if (!VALID_SERVICES.has(serviceName)) {
41
+ console.warn(`${Yellow('[!]')} ignoring unknown service in cookie file: ${serviceName}`);
42
+ } else if (!Array.isArray(cookies[serviceName])) {
43
+ console.warn(`${Yellow('[!]')} ${serviceName} in cookies file is not an array, ignoring it`);
44
+ } else if (cookies[serviceName].some(c => typeof c !== 'string')) {
45
+ console.warn(`${Yellow('[!]')} some cookie for ${serviceName} contains non-string value in cookies file`);
46
+ } else continue;
47
+
48
+ invalidCookies[serviceName] = cookies[serviceName];
49
+ delete cookies[serviceName];
50
+ }
51
+
52
+ if (!intervalId) {
53
+ intervalId = setInterval(() => writeChanges(cookiePath), WRITE_INTERVAL);
54
+ }
55
+
56
+ cluster.broadcast({ cookies });
57
+
58
+ console.log(`${Green('[✓]')} cookies loaded successfully!`);
59
+ } catch (e) {
60
+ console.error(`${Yellow('[!]')} failed to load cookies.`);
61
+ console.error('error:', e);
62
+ }
63
  }
64
 
65
+ const setupWorker = async () => {
66
+ cookies = (await cluster.waitFor('cookies')).cookies;
67
+ }
68
+
69
+ export const loadFromFile = async (path) => {
70
+ if (cluster.isPrimary) {
71
+ await setupMain(path);
72
+ } else if (cluster.isWorker) {
73
+ await setupWorker();
74
+ }
75
 
 
 
76
  dirty = false;
77
+ }
78
 
79
+ export const setup = async (path) => {
80
+ await loadFromFile(path);
81
+
82
+ if (isCluster) {
83
+ const messageHandler = (message) => {
84
+ if ('cookieUpdate' in message) {
85
+ const { cookieUpdate } = message;
86
+
87
+ if (cluster.isPrimary) {
88
+ dirty = true;
89
+ cluster.broadcast({ cookieUpdate });
90
+ }
91
+
92
+ const { service, idx, cookie } = cookieUpdate;
93
+ cookies[service][idx] = cookie;
94
+ }
95
+ }
96
+
97
+ if (cluster.isPrimary) {
98
+ cluster.mainOnMessage(messageHandler);
99
+ } else {
100
+ process.on('message', messageHandler);
101
+ }
102
+ }
103
  }
104
 
105
  export function getCookie(service) {
106
+ if (!VALID_SERVICES.has(service)) {
107
+ console.error(
108
+ `${Red('[!]')} ${service} not in allowed services list for cookies.`
109
+ + ' if adding a new cookie type, include it there.'
110
+ );
111
+ return;
112
+ }
113
+
114
  if (!cookies[service] || !cookies[service].length) return;
115
 
116
+ const idx = Math.floor(Math.random() * cookies[service].length);
117
+
118
+ const cookie = cookies[service][idx];
119
+ if (typeof cookie === 'string') {
120
+ cookies[service][idx] = Cookie.fromString(cookie);
 
121
  }
122
 
123
+ cookies[service][idx].meta = { service, idx };
124
+ return cookies[service][idx];
125
+ }
126
+
127
+ export function updateCookieValues(cookie, values) {
128
+ let changed = false;
129
 
130
+ for (const [ key, value ] of Object.entries(values)) {
131
+ changed = cookie.set(key, value) || changed;
132
+ }
133
+
134
+ if (changed && cookie.meta) {
135
+ dirty = true;
136
+ if (isCluster) {
137
+ const message = { cookieUpdate: { ...cookie.meta, cookie } };
138
+ cluster.send(message);
139
+ }
140
+ }
141
+
142
+ return changed;
143
  }
144
 
145
  export function updateCookie(cookie, headers) {
 
152
 
153
  cookie.unset(parsed.filter(c => c.expires < new Date()).map(c => c.name));
154
  parsed.filter(c => !c.expires || c.expires > new Date()).forEach(c => values[c.name] = c.value);
 
 
155
 
156
+ updateCookieValues(cookie, values);
157
+ }