added logic for auto-publish

This commit is contained in:
Omer Sabic 2024-06-13 14:45:43 +02:00
parent 8412cbc572
commit e6a8ef5f9e
3 changed files with 66 additions and 15 deletions

View File

@ -53,7 +53,8 @@ export const sites = pgTable("sites", {
subdomain_slug: text("subdomain_slug").$defaultFn(() => {
return makeid(10);
}),
social_medias: jsonb("social_medias")
social_medias: jsonb("social_medias"),
auto_publish: boolean("auto_publish").default(false)
});
export const articles = pgTable("articles", {

View File

@ -6,6 +6,8 @@ import { articles, articles as articlesTable, signups as signupsTable, sites, us
import { authMiddleware, authMiddlewareFn } from "../modules/middleware.js";
import { jsonToCsv, createBlogFromCaptions, createArticleSlug, getVideoById, env, getWhisperCaptions, getVideoWithCaptions } from "../utils/index.js";
const websubVerifyToken = "FQNI4Suzih";
/**
*
* @param {FastifyInstance} fastify
@ -28,7 +30,7 @@ export const dashboardRoutes = (fastify, _, done) => {
created_at: articlesTable.created_at
}).from(articlesTable)
.where(eq(articlesTable.site_id, site_id))
.orderBy(articlesTable.created_at).limit(5);
.orderBy(desc(articlesTable.created_at)).limit(5);
const recentSignups = await db.select({
email: signupsTable.email,
@ -338,6 +340,9 @@ export const dashboardRoutes = (fastify, _, done) => {
},
domain: {
type: ["string", "null"]
},
auto_publish: {
type: "boolean"
}
},
required: ["id"]
@ -364,6 +369,21 @@ export const dashboardRoutes = (fastify, _, done) => {
});
}
if(site.auto_publish !== req.body.auto_publish) {
const [user] = await db.select().from(users).where(eq(users.id, req.session.user_id));
if(!user) throw new Error("Problem getting user");
let form = new FormData();
form.set("hub.callback", env.PUBLIC_API_URL + "/webhooks/youtube");
form.set("hub.topic", "https://www.youtube.com/xml/feeds/videos.xml?channel_id=" + user.channel_id);
form.set("hub.verify", "async");
form.set("hub.mode", auto_publish ? "subscribe" : "unsubscribe");
form.set("hub.verify_token", websubVerifyToken);
await fetch("https://pubsubhubbub.appspot.com/subscribe", {
method: "POST",
body: form
});
}
const data = structuredClone(req.body);
delete data.id;

View File

@ -2,8 +2,10 @@
import { eq } from "drizzle-orm";
import { db } from "../db/index.js";
import { users } from "../db/schemas.js";
import { authMiddleware } from "../modules/middleware.js";
import { articles, sites, users } from "../db/schemas.js";
import { getVideoWithCaptions } from "../utils/youtube.js";
import { createBlogFromCaptions } from "../utils/ai.js";
import { createArticleSlug } from "../utils/index.js";
/**
*
@ -27,8 +29,10 @@ export const webhookRoutes = (fastify, _, done) => {
fastify.get("/youtube", async (req, reply) => {
// Check if the request contains the 'hub.challenge' query parameter
if (req.query["hub.challenge"]) {
if (req.query["hub.challenge"] && req.query["hub.verify_token"] === "FQNI4Suzih") {
// Respond with the challenge to verify the subscription
console.log(req.query)
console.log("verifying...", req.query["hub.challenge"]);
return reply.send(req.query["hub.challenge"]);
} else {
// Handle other cases or errors
@ -39,19 +43,45 @@ export const webhookRoutes = (fastify, _, done) => {
fastify.post("/youtube", async (req, reply) => {
const { headers, body } = req;
const contentType = headers['content-type'];
console.log(JSON.stringify(body.feed.contry))
// Check if the content type is 'application/atom+xml'
if (contentType === 'application/atom+xml') {
// Parse the XML payload
const { feed } = body;
// Example processing: log the video IDs of new videos
feed.entry.forEach(entry => {
const videoId = entry["yt:videoId"][0];
console.log(`New video uploaded: ${videoId}`);
});
try {
// Parse the XML payload
console.log(body)
const feed = body["feed"];
// Example processing: log the video IDs of new videos
const entry = feed.entry[0];
const [{users: user, sites: site}] = await db.select().from(users).leftJoin(sites, eq(users.id, sites.user_id)).where(eq(users.channel_id, "UC" + feed["yt:channelId"][0]));
if (!user || !site) throw new Error("User not found");
// Respond with a success status
return reply.code(200).send();
if (user.tokens < 3) throw new Error("Not enough tokens");
const videoId = entry["yt:videoId"][0];
const videoURL = `https://youtu.be/${videoId}`;
reply.code(200).send();
const video_data = await getVideoWithCaptions(videoURL);
const blog_content_json = await createBlogFromCaptions(video_data.captions, { title: video_data.title, description: video_data.description });
await db.insert(articles).values({
site_id: site.id,
title: blog_content_json.title,
content: blog_content_json.content,
meta_title: blog_content_json.meta_title,
meta_desc: blog_content_json.meta_desc,
excerp: blog_content_json.excerp,
source_video_id: videoId,
seo_slug: createArticleSlug(blog_content_json.title),
is_public: false
}).returning({ id: articles.id });
await db.update(users).set({
tokens: user.tokens - 3
}).where(eq(users.id, user.id));
// Respond with a success status
} catch (e) {
console.log(e)
return reply.code(500).send(e);
}
} else {
// Respond with an error status if the content type is not expected
return reply.code(400).send("Bad Request");