init
This commit is contained in:
@@ -0,0 +1,156 @@
|
||||
import config from "./config.ts";
|
||||
import { getUserByEmail } from "./utils/firebase.ts";
|
||||
import { insertObject, newPostgres, updateObject } from "./utils/postgres.ts";
|
||||
import { getAllActiveSubscriptions, getAllCustomers } from "./utils/stripe.ts";
|
||||
import { Client as DiscordClient, IntentsBitField } from "discord.js";
|
||||
|
||||
let lastSubs = "";
|
||||
let currentSubs = "";
|
||||
|
||||
const postgres2 = newPostgres();
|
||||
|
||||
// set up the Discord admin bot
|
||||
const discordBot = new DiscordClient({
|
||||
intents: [IntentsBitField.Flags.Guilds, IntentsBitField.Flags.GuildMembers],
|
||||
});
|
||||
if (config.DISCORD_ADMIN_BOT_TOKEN) {
|
||||
discordBot.login(config.DISCORD_ADMIN_BOT_TOKEN);
|
||||
// discordBot.once('ready', () => {
|
||||
// console.log(`Discord Bot "${discordBot?.user?.username}" ready`);
|
||||
// });
|
||||
}
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
setTimeout(syncSubscribers, 1000);
|
||||
}
|
||||
|
||||
setInterval(syncSubscribers, 60 * 1000);
|
||||
|
||||
async function syncSubscribers() {
|
||||
if (!config.STRIPE_SECRET_KEY || !config.FIREBASE_ADMIN_SDK_CONFIG) {
|
||||
return;
|
||||
}
|
||||
console.time("syncSubscribers");
|
||||
// Fetch subs, customers from stripe
|
||||
const [subs, customers] = await Promise.all([
|
||||
getAllActiveSubscriptions(),
|
||||
getAllCustomers(),
|
||||
]);
|
||||
|
||||
const emailMap = new Map();
|
||||
customers.forEach((cust) => {
|
||||
emailMap.set(cust.id, cust.email);
|
||||
});
|
||||
|
||||
console.log("%s subs in Stripe", subs.length);
|
||||
|
||||
const uidMap = new Map();
|
||||
for (let i = 0; i < subs.length; i += 50) {
|
||||
// Batch customers and fetch firebase data
|
||||
const batch = subs.slice(i, i + 50);
|
||||
const fbUsers = await Promise.all(
|
||||
batch
|
||||
.map((sub) =>
|
||||
emailMap.get(sub.customer)
|
||||
? getUserByEmail(emailMap.get(sub.customer))
|
||||
: null,
|
||||
)
|
||||
.filter(Boolean),
|
||||
);
|
||||
fbUsers.forEach((user) => {
|
||||
uidMap.set(user?.email, user?.uid);
|
||||
});
|
||||
}
|
||||
|
||||
let noUID = 0;
|
||||
// Create sub objects
|
||||
let result = subs
|
||||
.map((sub) => {
|
||||
let uid = uidMap.get(emailMap.get(sub.customer));
|
||||
if (!uid) {
|
||||
uid = emailMap.get(sub.customer);
|
||||
noUID += 1;
|
||||
}
|
||||
return {
|
||||
customerId: sub.customer,
|
||||
email: emailMap.get(sub.customer),
|
||||
status: sub.status,
|
||||
uid,
|
||||
};
|
||||
})
|
||||
.filter((sub) => sub.uid);
|
||||
console.log("%s subs to insert", result.length);
|
||||
console.log("%s subs do not have UID, using email", noUID);
|
||||
|
||||
const newResult = result.filter(
|
||||
(sub, index) =>
|
||||
index === result.findIndex((other) => sub.uid === other.uid),
|
||||
);
|
||||
console.log("%s deduped subs to insert", newResult.length);
|
||||
if (result.length !== newResult.length) {
|
||||
// Log the difference
|
||||
console.log(result.filter((x) => !newResult.includes(x)));
|
||||
}
|
||||
result = newResult;
|
||||
|
||||
currentSubs = result
|
||||
.map((sub) => sub.uid)
|
||||
.sort()
|
||||
.join();
|
||||
|
||||
// Upsert to DB
|
||||
// console.log(result);
|
||||
if (currentSubs !== lastSubs) {
|
||||
try {
|
||||
await postgres2?.query("BEGIN TRANSACTION");
|
||||
await postgres2?.query("DELETE FROM subscriber");
|
||||
await postgres2?.query('UPDATE room SET "isSubRoom" = false');
|
||||
for (let row of result) {
|
||||
await insertObject(postgres2, "subscriber", row);
|
||||
await updateObject(
|
||||
postgres2,
|
||||
"room",
|
||||
{ isSubRoom: true },
|
||||
{ owner: row.uid },
|
||||
);
|
||||
}
|
||||
await postgres2?.query("COMMIT");
|
||||
lastSubs = currentSubs;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
await postgres2?.query("ROLLBACK");
|
||||
}
|
||||
}
|
||||
if (
|
||||
discordBot.isReady() &&
|
||||
config.DISCORD_ADMIN_BOT_SERVER_ID &&
|
||||
config.DISCORD_ADMIN_BOT_SUB_ROLE_ID
|
||||
) {
|
||||
console.log("setting discord roles");
|
||||
// Update the sub status of users in Discord
|
||||
// Join the current subs with linked accounts
|
||||
const guild = discordBot.guilds.cache.get(
|
||||
config.DISCORD_ADMIN_BOT_SERVER_ID,
|
||||
);
|
||||
const role = guild?.roles.cache.get(config.DISCORD_ADMIN_BOT_SUB_ROLE_ID);
|
||||
const toUpdate = (
|
||||
await postgres2.query(
|
||||
`SELECT la.accountid from subscriber JOIN link_account la ON subscriber.uid = la.uid WHERE la.kind = 'discord'`,
|
||||
)
|
||||
).rows;
|
||||
console.log("%s users to set sub role", toUpdate.length);
|
||||
for (let row of toUpdate) {
|
||||
try {
|
||||
const user = await guild?.members.fetch(row.accountid);
|
||||
if (user && role) {
|
||||
console.log("assigning role %s to user %s", role, user.id);
|
||||
|
||||
await user.roles.add(role);
|
||||
}
|
||||
} catch (e: any) {
|
||||
console.log(e.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.timeEnd("syncSubscribers");
|
||||
}
|
||||
Reference in New Issue
Block a user