move cookies to processing
slight clean up and better example
This commit is contained in:
parent
a2216510b7
commit
fd0357e52d
8 changed files with 106 additions and 140 deletions
|
@ -1,43 +0,0 @@
|
||||||
import { strict as assert } from 'node:assert'
|
|
||||||
|
|
||||||
export default class Cookie {
|
|
||||||
constructor(input) {
|
|
||||||
assert(typeof input === 'object');
|
|
||||||
this._values = {}
|
|
||||||
this.set(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
set(values) {
|
|
||||||
Object.entries(values).forEach(
|
|
||||||
([ key, value ]) => this._values[key] = value
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
unset(keys) {
|
|
||||||
for (const key of keys)
|
|
||||||
delete this._values[key]
|
|
||||||
}
|
|
||||||
|
|
||||||
static fromString(str) {
|
|
||||||
const obj = {}
|
|
||||||
|
|
||||||
str
|
|
||||||
.split('; ')
|
|
||||||
.forEach(cookie => {
|
|
||||||
const key = cookie.split('=')[0]
|
|
||||||
const value = cookie.split('=').splice(1).join('=')
|
|
||||||
obj[key] = decodeURIComponent(value)
|
|
||||||
})
|
|
||||||
|
|
||||||
return new Cookie(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
toString() {
|
|
||||||
return Object.entries(this._values)
|
|
||||||
.map(([ name, value ]) => `${name}=${encodeURIComponent(value)}`)
|
|
||||||
.join('; ');
|
|
||||||
}
|
|
||||||
|
|
||||||
toJSON() { return this.toString() }
|
|
||||||
values() { return Object.freeze({ ...this._values }) }
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
{
|
|
||||||
"instagram": [
|
|
||||||
"cookie=asd; bla=bla; fake=cookie"
|
|
||||||
],
|
|
||||||
"youtube": [
|
|
||||||
"epic=google_cookie",
|
|
||||||
"epic=another_epic; youtube=cookie"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,78 +0,0 @@
|
||||||
import path from 'path'
|
|
||||||
import Cookie from './cookie.js'
|
|
||||||
import { readFile, writeFile } from 'fs/promises'
|
|
||||||
import { parse as parseSetCookie, splitCookiesString } from 'set-cookie-parser'
|
|
||||||
|
|
||||||
const WRITE_INTERVAL = 60000,
|
|
||||||
COOKIE_PATH = process.env.COOKIE_PATH,
|
|
||||||
COUNTER = Symbol('counter');
|
|
||||||
|
|
||||||
let cookies = {}, dirty = false, intervalId;
|
|
||||||
|
|
||||||
const setup = async () => {
|
|
||||||
try {
|
|
||||||
if (!COOKIE_PATH)
|
|
||||||
return
|
|
||||||
|
|
||||||
cookies = await readFile(COOKIE_PATH, 'utf8')
|
|
||||||
cookies = JSON.parse(cookies)
|
|
||||||
intervalId = setInterval(writeChanges, WRITE_INTERVAL)
|
|
||||||
} catch { /* no cookies for you */ }
|
|
||||||
}
|
|
||||||
|
|
||||||
setup()
|
|
||||||
|
|
||||||
function writeChanges() {
|
|
||||||
if (!dirty) return
|
|
||||||
dirty = false
|
|
||||||
|
|
||||||
writeFile(
|
|
||||||
COOKIE_PATH,
|
|
||||||
JSON.stringify(cookies, null, 4)
|
|
||||||
).catch(e => {
|
|
||||||
console.error('warn: cookies failed to save, stopping interval')
|
|
||||||
console.error('exception:', e)
|
|
||||||
clearInterval(intervalId)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getCookie(service) {
|
|
||||||
if (!cookies[service] || !cookies[service].length)
|
|
||||||
return
|
|
||||||
|
|
||||||
let n
|
|
||||||
if (cookies[service][COUNTER] === undefined) {
|
|
||||||
n = cookies[service][COUNTER] = 0
|
|
||||||
} else {
|
|
||||||
++cookies[service][COUNTER]
|
|
||||||
n = (cookies[service][COUNTER] %= cookies[service].length)
|
|
||||||
}
|
|
||||||
|
|
||||||
const cookie = cookies[service][n]
|
|
||||||
if (typeof cookie === 'string')
|
|
||||||
cookies[service][n] = Cookie.fromString(cookie)
|
|
||||||
|
|
||||||
return cookies[service][n]
|
|
||||||
}
|
|
||||||
|
|
||||||
// todo: expiry checking? domain checking?
|
|
||||||
// might be pointless for the purposes of cobalt
|
|
||||||
export function updateCookie(cookie, headers) {
|
|
||||||
const parsed = parseSetCookie(
|
|
||||||
splitCookiesString(headers.get('set-cookie'))
|
|
||||||
), values = {}
|
|
||||||
|
|
||||||
cookie.unset(
|
|
||||||
parsed
|
|
||||||
.filter(c => c.expires < new Date())
|
|
||||||
.map(c => c.name)
|
|
||||||
)
|
|
||||||
|
|
||||||
parsed
|
|
||||||
.filter(c => c.expires > new Date())
|
|
||||||
.forEach(c => values[c.name] = c.value);
|
|
||||||
|
|
||||||
cookie.set(values)
|
|
||||||
if (Object.keys(values).length)
|
|
||||||
dirty = true
|
|
||||||
}
|
|
37
src/modules/processing/cookie/cookie.js
Normal file
37
src/modules/processing/cookie/cookie.js
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
import { strict as assert } from 'node:assert';
|
||||||
|
|
||||||
|
export default class Cookie {
|
||||||
|
constructor(input) {
|
||||||
|
assert(typeof input === 'object');
|
||||||
|
this._values = {};
|
||||||
|
this.set(input)
|
||||||
|
}
|
||||||
|
set(values) {
|
||||||
|
Object.entries(values).forEach(
|
||||||
|
([ key, value ]) => this._values[key] = value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
unset(keys) {
|
||||||
|
for (const key of keys) delete this._values[key]
|
||||||
|
}
|
||||||
|
static fromString(str) {
|
||||||
|
const obj = {};
|
||||||
|
|
||||||
|
str.split('; ').forEach(cookie => {
|
||||||
|
const key = cookie.split('=')[0];
|
||||||
|
const value = cookie.split('=').splice(1).join('=');
|
||||||
|
obj[key] = decodeURIComponent(value)
|
||||||
|
})
|
||||||
|
|
||||||
|
return new Cookie(obj)
|
||||||
|
}
|
||||||
|
toString() {
|
||||||
|
return Object.entries(this._values).map(([ name, value ]) => `${name}=${encodeURIComponent(value)}`).join('; ')
|
||||||
|
}
|
||||||
|
toJSON() {
|
||||||
|
return this.toString()
|
||||||
|
}
|
||||||
|
values() {
|
||||||
|
return Object.freeze({ ...this._values })
|
||||||
|
}
|
||||||
|
}
|
5
src/modules/processing/cookie/cookies_example.json
Normal file
5
src/modules/processing/cookie/cookies_example.json
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"instagram": [
|
||||||
|
"mid=replace; ig_did=this; csrftoken=cookie"
|
||||||
|
]
|
||||||
|
}
|
58
src/modules/processing/cookie/manager.js
Normal file
58
src/modules/processing/cookie/manager.js
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
import Cookie from './cookie.js';
|
||||||
|
import { readFile, writeFile } from 'fs/promises';
|
||||||
|
import { parse as parseSetCookie, splitCookiesString } from 'set-cookie-parser';
|
||||||
|
|
||||||
|
const WRITE_INTERVAL = 60000,
|
||||||
|
COOKIE_PATH = process.env.COOKIE_PATH,
|
||||||
|
COUNTER = Symbol('counter');
|
||||||
|
|
||||||
|
let cookies = {}, dirty = false, intervalId;
|
||||||
|
|
||||||
|
const setup = async () => {
|
||||||
|
try {
|
||||||
|
if (!COOKIE_PATH) return;
|
||||||
|
|
||||||
|
cookies = await readFile(COOKIE_PATH, 'utf8');
|
||||||
|
cookies = JSON.parse(cookies);
|
||||||
|
intervalId = setInterval(writeChanges, WRITE_INTERVAL)
|
||||||
|
} catch { /* no cookies for you */ }
|
||||||
|
}
|
||||||
|
|
||||||
|
setup();
|
||||||
|
|
||||||
|
function writeChanges() {
|
||||||
|
if (!dirty) return;
|
||||||
|
dirty = false;
|
||||||
|
|
||||||
|
writeFile(COOKIE_PATH, JSON.stringify(cookies, null, 4)).catch(() => {
|
||||||
|
clearInterval(intervalId)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCookie(service) {
|
||||||
|
if (!cookies[service] || !cookies[service].length) return;
|
||||||
|
|
||||||
|
let n;
|
||||||
|
if (cookies[service][COUNTER] === undefined) {
|
||||||
|
n = cookies[service][COUNTER] = 0
|
||||||
|
} else {
|
||||||
|
++cookies[service][COUNTER]
|
||||||
|
n = (cookies[service][COUNTER] %= cookies[service].length)
|
||||||
|
}
|
||||||
|
|
||||||
|
const cookie = cookies[service][n];
|
||||||
|
if (typeof cookie === 'string') cookies[service][n] = Cookie.fromString(cookie);
|
||||||
|
|
||||||
|
return cookies[service][n]
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateCookie(cookie, headers) {
|
||||||
|
const parsed = parseSetCookie(splitCookiesString(headers.get('set-cookie'))),
|
||||||
|
values = {}
|
||||||
|
|
||||||
|
cookie.unset(parsed.filter(c => c.expires < new Date()).map(c => c.name));
|
||||||
|
parsed.filter(c => c.expires > new Date()).forEach(c => values[c.name] = c.value);
|
||||||
|
|
||||||
|
cookie.set(values);
|
||||||
|
if (Object.keys(values).length) dirty = true
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
import { createStream } from "../../stream/manage.js";
|
import { createStream } from "../../stream/manage.js";
|
||||||
import { genericUserAgent } from "../../config.js";
|
import { genericUserAgent } from "../../config.js";
|
||||||
import { getCookie, updateCookie } from '../../cookie/manager.js';
|
import { getCookie, updateCookie } from '../cookie/manager.js';
|
||||||
|
|
||||||
export default async function(obj) {
|
export default async function(obj) {
|
||||||
let data;
|
let data;
|
||||||
|
@ -67,7 +67,11 @@ export default async function(obj) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (single) {
|
if (single) {
|
||||||
return { urls: single, filename: `instagram_${obj.id}.mp4`, audioFilename: `instagram_${obj.id}_audio` }
|
return {
|
||||||
|
urls: single,
|
||||||
|
filename: `instagram_${obj.id}.mp4`,
|
||||||
|
audioFilename: `instagram_${obj.id}_audio`
|
||||||
|
}
|
||||||
} else if (multiple.length) {
|
} else if (multiple.length) {
|
||||||
return { picker: multiple }
|
return { picker: multiple }
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -834,14 +834,6 @@
|
||||||
}
|
}
|
||||||
}],
|
}],
|
||||||
"instagram": [{
|
"instagram": [{
|
||||||
"name": "several videos in a post (picker)",
|
|
||||||
"url": "https://www.instagram.com/p/CqifaD0qiDt/",
|
|
||||||
"params": {},
|
|
||||||
"expected": {
|
|
||||||
"code": 200,
|
|
||||||
"status": "picker"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
"name": "reel",
|
"name": "reel",
|
||||||
"url": "https://www.instagram.com/reel/CoEBV3eM4QR/",
|
"url": "https://www.instagram.com/reel/CoEBV3eM4QR/",
|
||||||
"params": {},
|
"params": {},
|
||||||
|
|
Loading…
Reference in a new issue