94 lines
3.4 KiB
JavaScript
94 lines
3.4 KiB
JavaScript
|
|
import { simpleParser } from 'mailparser';
|
|
import { load } from 'cheerio'
|
|
|
|
const definitions = [
|
|
{
|
|
platform: 'chaturbate',
|
|
selectors: {
|
|
channel: 'td[id*="onlinemessage"] a:nth-child(1)'
|
|
},
|
|
from: 'follownotify@bk.chaturbate.com',
|
|
template: 'https://chaturbate.com/:channel'
|
|
},
|
|
{
|
|
platform: 'fansly',
|
|
selectors: {
|
|
channel: ($) => $("a[href*='/live/']").attr('href').toString().split('/').at(-1),
|
|
displayName: 'div[class*="message-col"] div:nth-child(5)',
|
|
userId: ($) => $("img[src*='/api/v1/account/']").attr('src').toString().split('/').at(-2),
|
|
avatar: ($) => $("img[src*='/api/v1/account/']").attr('src').toString()
|
|
},
|
|
from: 'no-reply@fansly.com',
|
|
template: 'https://fansly.com/:channel',
|
|
regex: /https:\/\/fansly.com\/live\/([a-zA-Z0-9_]+)/
|
|
}
|
|
]
|
|
|
|
function render(template, values) {
|
|
// console.log(`values=${values}`)
|
|
// console.log(values)
|
|
return template.replace(/:([a-zA-Z0-9_]+)/g, (match, key) => {
|
|
// Replace :channel with the corresponding property from the values object
|
|
return values[key] || match;
|
|
});
|
|
}
|
|
|
|
|
|
/**
|
|
* checkEmail
|
|
*
|
|
* Check an e-mail for go-live notification content.
|
|
*
|
|
* { isMatch, url, platform, channel, displayName, date }
|
|
*
|
|
* @param {String} body raw mail body
|
|
* @returns {Object} result
|
|
* @returns {Boolean} result.isMatch true if e-mail contains a go-live notification
|
|
* @returns {String} result.url example: https://fansly.com/projektmelody
|
|
* @returns {String} result.platform example: fansly
|
|
* @returns {String} result.channel example: projektmelody
|
|
* @returns {String} result.displayName example: ProjektMelody
|
|
* @returns {String} result.date example: 2024-05-31T01:02:00.000Z
|
|
* @returns {String|null} result.userId Varies by platform. Some platforms don't have the userId in the e-mail, so it's null.
|
|
* fansly example: '555722198917066752'
|
|
*/
|
|
export async function checkEmail (body) {
|
|
|
|
const mail = await simpleParser(body)
|
|
if (!mail?.html) {
|
|
console.log(`mail.html was not truthy. This means the e-mail was text-only mode. This also means the e-mail is not a go-live notification.`);
|
|
return { isMatch: false }
|
|
}
|
|
|
|
let res = {}
|
|
let def = definitions.find((def) => def.from === mail.from.value[0].address)
|
|
if (!def) return { isMatch: false, channel: null, platform: null, url: null };
|
|
res.isMatch = true
|
|
|
|
// Step 0, get values from e-mail metadata
|
|
res.platform = def.platform
|
|
res.date = new Date(mail.date).toISOString()
|
|
|
|
// Step 1, get values using CSS selectors
|
|
const $ = load(mail.html)
|
|
for (const s in def.selectors) {
|
|
res[s] = (def.selectors[s] instanceof Object) ? def.selectors[s]($) : $(def.selectors[s]).text()
|
|
}
|
|
|
|
// console.log(`res.url=${res.url} res.userId=${res.userId}`)
|
|
|
|
// Step 2, get values using regex & templates
|
|
res.channel = (() => {
|
|
if (res.channel) return res.channel;
|
|
if (def.regex && res.url) return def.regex.exec(res.url).at(1);
|
|
})()
|
|
|
|
res.userId = res.userId || null
|
|
res.avatar = res.avatar || null
|
|
|
|
res.url = res.url || render(def.template, { channel: res.channel })
|
|
|
|
|
|
return res
|
|
} |