├── .gitignore ├── README.md ├── config └── aiConfig.js ├── index.js ├── package-lock.json ├── package.json ├── service ├── generateArticle.js ├── generateImage.js └── generateTopic.js ├── utills └── facebookPoster.js └── vercel.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env 3 | .env.local 4 | .env.production 5 | images -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 📰 AI Article Generator 2 | 3 | An automated system that creates and posts engaging articles with custom-generated images directly to a Facebook page—powered by multiple AI services and orchestrated using Node.js. 4 | 5 | This project demonstrates how artificial intelligence can streamline content creation and social media automation. Every morning at 9 AM, a Node.js script kicks off a seamless workflow: 6 | 7 | This end-to-end process runs automatically, delivering fresh, contextual content without manual effort. 8 | 9 | ## 🚀 Overview 10 | 11 | 1. **Topic Generation**: Using **Mistral AI**, the system selects a trending or compelling topic for the day. 12 | 2. **Article Writing**: Mistral AI then generates a full article based on the selected topic. 13 | 3. **Image Creation**: Key concepts from the article are extracted and sent to the **Hugging Face Image Generator AI**, which produces a relevant visual. 14 | 4. **Content Publishing**: The final article and image are published to a Facebook page using the **Facebook Graph API**. 15 | 16 | ## 🧰 Technologies Used 17 | 18 | - **Node.js** – The backbone of the automation and integration logic. 19 | - **Mistral AI** – For generating article topics and writing full-length articles. 20 | - **Hugging Face Image Generator** – To generate images based on article content. 21 | - **ImgBB Image Hosting** – To upload images made from Hugging Face Image Generator. 22 | - **Facebook Graph API** – For posting articles and images to Facebook. 23 | 24 | ## 🧑‍💻 Getting Started 25 | 26 | ### ⚙️ Prerequisites 27 | 28 | - **Node.js** (v18 or newer recommended) 29 | - **Mistral AI API key** (for topic and article generation) 30 | - **Hugging Face API key** (for image generation) 31 | - **ImgBB API key** (for image uploading and link generation) 32 | - **Facebook Developer account** (for Graph API access) 33 | 34 | ### 📦 Installation 35 | 36 | 1. **Clone and setup the project** 37 | 38 | ```bash 39 | git clone 40 | cd aiArticleGenerator 41 | npm install 42 | ``` 43 | 44 | 2. **Environment Configuration** 45 | 46 | Create a `.env` file and Copy the below and update with your values: 47 | 48 | ```bash 49 | # Site 50 | SITE_NAME="your-site-name" 51 | SITE_URL="your-site-url" 52 | 53 | # Mistral AI 54 | OPENROUTER_API_KEY="your-openrouter-api-key" 55 | 56 | # Hugging Face AI 57 | HUGGINGFACE_API_KEY="your-huggingface-api-key" 58 | 59 | # ImgBB 60 | IMGBB_API_KEY="your-imgbb-api-key" 61 | 62 | # Facebook 63 | FB_PAGE_ID="your-facebook-page-id" 64 | FB_PAGE_ACCESS_TOKEN="your-facebook-access-token" 65 | ``` 66 | 67 | 3. **Run Development Server** 68 | 69 | ```bash 70 | npm start 71 | ``` 72 | 73 | This command starts the automation workflow. It will trigger the daily cron job, generate a topic and article, create an image, upload it, and post everything to your configured Facebook page. You should see logs in the terminal indicating each step of the process. 74 | 75 | **Testing the Workflow Manually:** 76 | If you want to test the workflow immediately (without waiting for the 9AM cron job), you can uncomment the following code in `index.js`: 77 | 78 | ```js 79 | // (async () => { 80 | // await runGenerator(); 81 | // })(); 82 | ``` 83 | 84 | This will run the generator instantly when you start the server. 85 | 86 | ## 📁 Project Structure 87 | 88 | ``` 89 | aiArticleGenerator/ 90 | ├── config/ # Configuration Folder 91 | │ └── aiConfig.js # AI configuration and API keys 92 | ├── service/ # Service logics 93 | │ └── generateArticle.js # Generates articles using AI 94 | │ └── generateImage.js # Generates images using AI 95 | │ └── generateTopic.js # Generates topics using AI 96 | ├── utills/ # Utility functions 97 | │ └── facebookPoster.js # Posts content to Facebook 98 | ├── .env # Environment variables 99 | ├── index.js # Main entry point 100 | ├── package.json # Project metadata and dependencies 101 | ├── README.md # Project documentation 102 | └── vercel.json # Vercel deployment configuration 103 | └── LICENSE # License information 104 | ``` 105 | 106 | ## ✨ Key Features Explained 107 | 108 | - **Automated Topic Generation**: Uses Mistral AI to select trending or relevant topics every day. 109 | - **AI-Powered Article Writing**: Generates full-length articles based on the chosen topic using advanced language models. 110 | - **Custom Image Creation**: Extracts key concepts from articles and generates unique images via Hugging Face Image Generator. 111 | - **Image Hosting Integration**: Uploads generated images to ImgBB for reliable hosting and sharing. 112 | - **Seamless Facebook Publishing**: Automatically posts articles and images to a Facebook page using the Facebook Graph API. 113 | - **Daily Cron Job**: The entire workflow is triggered automatically every morning at 9 AM using a scheduled cron job, ensuring consistent and timely content delivery. 114 | - **Environment-Based Configuration**: All sensitive credentials and configuration are managed securely via environment variables. 115 | 116 | ## 🚢 Deployment 117 | 118 | ### 🌐 Vercel Deployment (Recommended) 119 | 120 | 1. **Connect to Vercel** 121 | 122 | ```bash 123 | npm install -g vercel 124 | vercel login 125 | vercel 126 | ``` 127 | 128 | 2. **Environment Variables** 129 | Set all environment variables in Vercel dashboard 130 | 131 | ## 🙌 Contributing 132 | 133 | 1. Fork the repository 134 | 2. Create your feature branch (`git checkout -b feature/amazing-feature`) 135 | 3. Commit your changes (`git commit -m 'Add some amazing feature'`) 136 | 4. Push to the branch (`git push origin feature/amazing-feature`) 137 | 5. Open a Pull Request 138 | 139 | ## 📄 License 140 | 141 | This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. 142 | 143 | ## 🆘 Support 144 | 145 | For support create an issue in the repository. 146 | 147 | ## 🙏 Acknowledgments 148 | 149 | - Inspired by the potential of AI to automate and enhance digital content creation. 150 | - Built through continuous learning, experimentation, and problem-solving. 151 | - Thanks to open-source communities and AI service providers for their valuable resources and APIs. -------------------------------------------------------------------------------- /config/aiConfig.js: -------------------------------------------------------------------------------- 1 | import dotenv from "dotenv"; 2 | dotenv.config(); 3 | 4 | export const config = { 5 | apiKey: process.env.OPENROUTER_API_KEY, 6 | model: "cognitivecomputations/dolphin-mistral-24b-venice-edition:free", 7 | headers: { 8 | Authorization: `Bearer ${process.env.OPENROUTER_API_KEY}`, 9 | "Content-Type": "application/json", 10 | "HTTP-Referer": process.env.SITE_URL || "https://atikuzzaman.vercel.app", 11 | "X-Title": process.env.SITE_NAME || "Atikuzzaman", 12 | }, 13 | huggingfaceApiKey: process.env.HUGGINGFACE_API_KEY, 14 | imgbbApiKey: process.env.IMGBB_API_KEY, 15 | fbAccessToken: process.env.FB_PAGE_ACCESS_TOKEN, 16 | pageid: process.env.FB_PAGE_ID, 17 | }; 18 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import cron from "node-cron"; 2 | import { generateTopic } from "./service/generateTopic.js"; 3 | import { generateArticle } from "./service/generateArticle.js"; 4 | import { generateImage } from "./service/generateImage.js"; 5 | import { createPublicPost } from "./utills/facebookPoster.js"; 6 | 7 | async function runGenerator() { 8 | try { 9 | console.log("Starting new cycle at:", new Date().toLocaleString()); 10 | const topic = await generateTopic(); 11 | const [article, image] = await Promise.all([ 12 | generateArticle(topic), 13 | generateImage({ inputs: topic }), 14 | ]); 15 | 16 | if (!article || !image) { 17 | console.warn("Article or image missing. Skipping Facebook post."); 18 | return; 19 | } 20 | console.log(` 21 | topic: ${topic} 22 | article: ${article} 23 | img: ${image}`); 24 | 25 | await createPublicPost(article, image); 26 | } catch (error) { 27 | console.error("Problem in main function:", error.message); 28 | } 29 | } 30 | 31 | // (async () => { 32 | // await runGenerator(); 33 | // })(); 34 | 35 | cron.schedule( 36 | "0 8 * * *", 37 | async () => { 38 | console.log(" Cron job triggered at: 8:30 AM"); 39 | await runGenerator(); 40 | }, 41 | { 42 | timezone: "Asia/Dhaka", 43 | } 44 | ); 45 | 46 | console.log("Background worker started. Waiting for scheduled jobs..."); 47 | setInterval(() => {}, 1000 * 60 * 60); 48 | 49 | process.on("SIGTERM", () => { 50 | console.log("SIGTERM received, exiting gracefully..."); 51 | process.exit(0); 52 | }); 53 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "generatepost", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "generatepost", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "axios": "^1.11.0", 13 | "dotenv": "^17.2.1", 14 | "form-data": "^4.0.4", 15 | "node-cron": "^4.2.1", 16 | "node-fetch": "^3.3.2", 17 | "replicate": "^1.0.1" 18 | } 19 | }, 20 | "node_modules/abort-controller": { 21 | "version": "3.0.0", 22 | "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", 23 | "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", 24 | "license": "MIT", 25 | "optional": true, 26 | "dependencies": { 27 | "event-target-shim": "^5.0.0" 28 | }, 29 | "engines": { 30 | "node": ">=6.5" 31 | } 32 | }, 33 | "node_modules/asynckit": { 34 | "version": "0.4.0", 35 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 36 | "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", 37 | "license": "MIT" 38 | }, 39 | "node_modules/axios": { 40 | "version": "1.11.0", 41 | "resolved": "https://registry.npmjs.org/axios/-/axios-1.11.0.tgz", 42 | "integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==", 43 | "license": "MIT", 44 | "dependencies": { 45 | "follow-redirects": "^1.15.6", 46 | "form-data": "^4.0.4", 47 | "proxy-from-env": "^1.1.0" 48 | } 49 | }, 50 | "node_modules/base64-js": { 51 | "version": "1.5.1", 52 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", 53 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", 54 | "funding": [ 55 | { 56 | "type": "github", 57 | "url": "https://github.com/sponsors/feross" 58 | }, 59 | { 60 | "type": "patreon", 61 | "url": "https://www.patreon.com/feross" 62 | }, 63 | { 64 | "type": "consulting", 65 | "url": "https://feross.org/support" 66 | } 67 | ], 68 | "license": "MIT", 69 | "optional": true 70 | }, 71 | "node_modules/buffer": { 72 | "version": "6.0.3", 73 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", 74 | "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", 75 | "funding": [ 76 | { 77 | "type": "github", 78 | "url": "https://github.com/sponsors/feross" 79 | }, 80 | { 81 | "type": "patreon", 82 | "url": "https://www.patreon.com/feross" 83 | }, 84 | { 85 | "type": "consulting", 86 | "url": "https://feross.org/support" 87 | } 88 | ], 89 | "license": "MIT", 90 | "optional": true, 91 | "dependencies": { 92 | "base64-js": "^1.3.1", 93 | "ieee754": "^1.2.1" 94 | } 95 | }, 96 | "node_modules/call-bind-apply-helpers": { 97 | "version": "1.0.2", 98 | "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", 99 | "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", 100 | "license": "MIT", 101 | "dependencies": { 102 | "es-errors": "^1.3.0", 103 | "function-bind": "^1.1.2" 104 | }, 105 | "engines": { 106 | "node": ">= 0.4" 107 | } 108 | }, 109 | "node_modules/combined-stream": { 110 | "version": "1.0.8", 111 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 112 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 113 | "license": "MIT", 114 | "dependencies": { 115 | "delayed-stream": "~1.0.0" 116 | }, 117 | "engines": { 118 | "node": ">= 0.8" 119 | } 120 | }, 121 | "node_modules/data-uri-to-buffer": { 122 | "version": "4.0.1", 123 | "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", 124 | "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", 125 | "license": "MIT", 126 | "engines": { 127 | "node": ">= 12" 128 | } 129 | }, 130 | "node_modules/delayed-stream": { 131 | "version": "1.0.0", 132 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 133 | "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", 134 | "license": "MIT", 135 | "engines": { 136 | "node": ">=0.4.0" 137 | } 138 | }, 139 | "node_modules/dotenv": { 140 | "version": "17.2.1", 141 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.1.tgz", 142 | "integrity": "sha512-kQhDYKZecqnM0fCnzI5eIv5L4cAe/iRI+HqMbO/hbRdTAeXDG+M9FjipUxNfbARuEg4iHIbhnhs78BCHNbSxEQ==", 143 | "license": "BSD-2-Clause", 144 | "engines": { 145 | "node": ">=12" 146 | }, 147 | "funding": { 148 | "url": "https://dotenvx.com" 149 | } 150 | }, 151 | "node_modules/dunder-proto": { 152 | "version": "1.0.1", 153 | "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", 154 | "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", 155 | "license": "MIT", 156 | "dependencies": { 157 | "call-bind-apply-helpers": "^1.0.1", 158 | "es-errors": "^1.3.0", 159 | "gopd": "^1.2.0" 160 | }, 161 | "engines": { 162 | "node": ">= 0.4" 163 | } 164 | }, 165 | "node_modules/es-define-property": { 166 | "version": "1.0.1", 167 | "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", 168 | "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", 169 | "license": "MIT", 170 | "engines": { 171 | "node": ">= 0.4" 172 | } 173 | }, 174 | "node_modules/es-errors": { 175 | "version": "1.3.0", 176 | "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", 177 | "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", 178 | "license": "MIT", 179 | "engines": { 180 | "node": ">= 0.4" 181 | } 182 | }, 183 | "node_modules/es-object-atoms": { 184 | "version": "1.1.1", 185 | "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", 186 | "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", 187 | "license": "MIT", 188 | "dependencies": { 189 | "es-errors": "^1.3.0" 190 | }, 191 | "engines": { 192 | "node": ">= 0.4" 193 | } 194 | }, 195 | "node_modules/es-set-tostringtag": { 196 | "version": "2.1.0", 197 | "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", 198 | "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", 199 | "license": "MIT", 200 | "dependencies": { 201 | "es-errors": "^1.3.0", 202 | "get-intrinsic": "^1.2.6", 203 | "has-tostringtag": "^1.0.2", 204 | "hasown": "^2.0.2" 205 | }, 206 | "engines": { 207 | "node": ">= 0.4" 208 | } 209 | }, 210 | "node_modules/event-target-shim": { 211 | "version": "5.0.1", 212 | "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", 213 | "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", 214 | "license": "MIT", 215 | "optional": true, 216 | "engines": { 217 | "node": ">=6" 218 | } 219 | }, 220 | "node_modules/events": { 221 | "version": "3.3.0", 222 | "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", 223 | "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", 224 | "license": "MIT", 225 | "optional": true, 226 | "engines": { 227 | "node": ">=0.8.x" 228 | } 229 | }, 230 | "node_modules/fetch-blob": { 231 | "version": "3.2.0", 232 | "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", 233 | "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", 234 | "funding": [ 235 | { 236 | "type": "github", 237 | "url": "https://github.com/sponsors/jimmywarting" 238 | }, 239 | { 240 | "type": "paypal", 241 | "url": "https://paypal.me/jimmywarting" 242 | } 243 | ], 244 | "license": "MIT", 245 | "dependencies": { 246 | "node-domexception": "^1.0.0", 247 | "web-streams-polyfill": "^3.0.3" 248 | }, 249 | "engines": { 250 | "node": "^12.20 || >= 14.13" 251 | } 252 | }, 253 | "node_modules/follow-redirects": { 254 | "version": "1.15.9", 255 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", 256 | "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", 257 | "funding": [ 258 | { 259 | "type": "individual", 260 | "url": "https://github.com/sponsors/RubenVerborgh" 261 | } 262 | ], 263 | "license": "MIT", 264 | "engines": { 265 | "node": ">=4.0" 266 | }, 267 | "peerDependenciesMeta": { 268 | "debug": { 269 | "optional": true 270 | } 271 | } 272 | }, 273 | "node_modules/form-data": { 274 | "version": "4.0.4", 275 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", 276 | "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", 277 | "license": "MIT", 278 | "dependencies": { 279 | "asynckit": "^0.4.0", 280 | "combined-stream": "^1.0.8", 281 | "es-set-tostringtag": "^2.1.0", 282 | "hasown": "^2.0.2", 283 | "mime-types": "^2.1.12" 284 | }, 285 | "engines": { 286 | "node": ">= 6" 287 | } 288 | }, 289 | "node_modules/formdata-polyfill": { 290 | "version": "4.0.10", 291 | "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", 292 | "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", 293 | "license": "MIT", 294 | "dependencies": { 295 | "fetch-blob": "^3.1.2" 296 | }, 297 | "engines": { 298 | "node": ">=12.20.0" 299 | } 300 | }, 301 | "node_modules/function-bind": { 302 | "version": "1.1.2", 303 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 304 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", 305 | "license": "MIT", 306 | "funding": { 307 | "url": "https://github.com/sponsors/ljharb" 308 | } 309 | }, 310 | "node_modules/get-intrinsic": { 311 | "version": "1.3.0", 312 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", 313 | "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", 314 | "license": "MIT", 315 | "dependencies": { 316 | "call-bind-apply-helpers": "^1.0.2", 317 | "es-define-property": "^1.0.1", 318 | "es-errors": "^1.3.0", 319 | "es-object-atoms": "^1.1.1", 320 | "function-bind": "^1.1.2", 321 | "get-proto": "^1.0.1", 322 | "gopd": "^1.2.0", 323 | "has-symbols": "^1.1.0", 324 | "hasown": "^2.0.2", 325 | "math-intrinsics": "^1.1.0" 326 | }, 327 | "engines": { 328 | "node": ">= 0.4" 329 | }, 330 | "funding": { 331 | "url": "https://github.com/sponsors/ljharb" 332 | } 333 | }, 334 | "node_modules/get-proto": { 335 | "version": "1.0.1", 336 | "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", 337 | "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", 338 | "license": "MIT", 339 | "dependencies": { 340 | "dunder-proto": "^1.0.1", 341 | "es-object-atoms": "^1.0.0" 342 | }, 343 | "engines": { 344 | "node": ">= 0.4" 345 | } 346 | }, 347 | "node_modules/gopd": { 348 | "version": "1.2.0", 349 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", 350 | "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", 351 | "license": "MIT", 352 | "engines": { 353 | "node": ">= 0.4" 354 | }, 355 | "funding": { 356 | "url": "https://github.com/sponsors/ljharb" 357 | } 358 | }, 359 | "node_modules/has-symbols": { 360 | "version": "1.1.0", 361 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", 362 | "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", 363 | "license": "MIT", 364 | "engines": { 365 | "node": ">= 0.4" 366 | }, 367 | "funding": { 368 | "url": "https://github.com/sponsors/ljharb" 369 | } 370 | }, 371 | "node_modules/has-tostringtag": { 372 | "version": "1.0.2", 373 | "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", 374 | "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", 375 | "license": "MIT", 376 | "dependencies": { 377 | "has-symbols": "^1.0.3" 378 | }, 379 | "engines": { 380 | "node": ">= 0.4" 381 | }, 382 | "funding": { 383 | "url": "https://github.com/sponsors/ljharb" 384 | } 385 | }, 386 | "node_modules/hasown": { 387 | "version": "2.0.2", 388 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", 389 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", 390 | "license": "MIT", 391 | "dependencies": { 392 | "function-bind": "^1.1.2" 393 | }, 394 | "engines": { 395 | "node": ">= 0.4" 396 | } 397 | }, 398 | "node_modules/ieee754": { 399 | "version": "1.2.1", 400 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", 401 | "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", 402 | "funding": [ 403 | { 404 | "type": "github", 405 | "url": "https://github.com/sponsors/feross" 406 | }, 407 | { 408 | "type": "patreon", 409 | "url": "https://www.patreon.com/feross" 410 | }, 411 | { 412 | "type": "consulting", 413 | "url": "https://feross.org/support" 414 | } 415 | ], 416 | "license": "BSD-3-Clause", 417 | "optional": true 418 | }, 419 | "node_modules/math-intrinsics": { 420 | "version": "1.1.0", 421 | "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", 422 | "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", 423 | "license": "MIT", 424 | "engines": { 425 | "node": ">= 0.4" 426 | } 427 | }, 428 | "node_modules/mime-db": { 429 | "version": "1.52.0", 430 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 431 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 432 | "license": "MIT", 433 | "engines": { 434 | "node": ">= 0.6" 435 | } 436 | }, 437 | "node_modules/mime-types": { 438 | "version": "2.1.35", 439 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 440 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 441 | "license": "MIT", 442 | "dependencies": { 443 | "mime-db": "1.52.0" 444 | }, 445 | "engines": { 446 | "node": ">= 0.6" 447 | } 448 | }, 449 | "node_modules/node-cron": { 450 | "version": "4.2.1", 451 | "resolved": "https://registry.npmjs.org/node-cron/-/node-cron-4.2.1.tgz", 452 | "integrity": "sha512-lgimEHPE/QDgFlywTd8yTR61ptugX3Qer29efeyWw2rv259HtGBNn1vZVmp8lB9uo9wC0t/AT4iGqXxia+CJFg==", 453 | "license": "ISC", 454 | "engines": { 455 | "node": ">=6.0.0" 456 | } 457 | }, 458 | "node_modules/node-domexception": { 459 | "version": "1.0.0", 460 | "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", 461 | "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", 462 | "deprecated": "Use your platform's native DOMException instead", 463 | "funding": [ 464 | { 465 | "type": "github", 466 | "url": "https://github.com/sponsors/jimmywarting" 467 | }, 468 | { 469 | "type": "github", 470 | "url": "https://paypal.me/jimmywarting" 471 | } 472 | ], 473 | "license": "MIT", 474 | "engines": { 475 | "node": ">=10.5.0" 476 | } 477 | }, 478 | "node_modules/node-fetch": { 479 | "version": "3.3.2", 480 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", 481 | "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", 482 | "license": "MIT", 483 | "dependencies": { 484 | "data-uri-to-buffer": "^4.0.0", 485 | "fetch-blob": "^3.1.4", 486 | "formdata-polyfill": "^4.0.10" 487 | }, 488 | "engines": { 489 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0" 490 | }, 491 | "funding": { 492 | "type": "opencollective", 493 | "url": "https://opencollective.com/node-fetch" 494 | } 495 | }, 496 | "node_modules/process": { 497 | "version": "0.11.10", 498 | "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", 499 | "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", 500 | "license": "MIT", 501 | "optional": true, 502 | "engines": { 503 | "node": ">= 0.6.0" 504 | } 505 | }, 506 | "node_modules/proxy-from-env": { 507 | "version": "1.1.0", 508 | "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", 509 | "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", 510 | "license": "MIT" 511 | }, 512 | "node_modules/readable-stream": { 513 | "version": "4.7.0", 514 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", 515 | "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", 516 | "license": "MIT", 517 | "optional": true, 518 | "dependencies": { 519 | "abort-controller": "^3.0.0", 520 | "buffer": "^6.0.3", 521 | "events": "^3.3.0", 522 | "process": "^0.11.10", 523 | "string_decoder": "^1.3.0" 524 | }, 525 | "engines": { 526 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 527 | } 528 | }, 529 | "node_modules/replicate": { 530 | "version": "1.0.1", 531 | "resolved": "https://registry.npmjs.org/replicate/-/replicate-1.0.1.tgz", 532 | "integrity": "sha512-EY+rK1YR5bKHcM9pd6WyaIbv6m2aRIvHfHDh51j/LahlHTLKemTYXF6ptif2sLa+YospupAsIoxw8Ndt5nI3vg==", 533 | "license": "Apache-2.0", 534 | "engines": { 535 | "git": ">=2.11.0", 536 | "node": ">=18.0.0", 537 | "npm": ">=7.19.0", 538 | "yarn": ">=1.7.0" 539 | }, 540 | "optionalDependencies": { 541 | "readable-stream": ">=4.0.0" 542 | } 543 | }, 544 | "node_modules/safe-buffer": { 545 | "version": "5.2.1", 546 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 547 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 548 | "funding": [ 549 | { 550 | "type": "github", 551 | "url": "https://github.com/sponsors/feross" 552 | }, 553 | { 554 | "type": "patreon", 555 | "url": "https://www.patreon.com/feross" 556 | }, 557 | { 558 | "type": "consulting", 559 | "url": "https://feross.org/support" 560 | } 561 | ], 562 | "license": "MIT", 563 | "optional": true 564 | }, 565 | "node_modules/string_decoder": { 566 | "version": "1.3.0", 567 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", 568 | "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", 569 | "license": "MIT", 570 | "optional": true, 571 | "dependencies": { 572 | "safe-buffer": "~5.2.0" 573 | } 574 | }, 575 | "node_modules/web-streams-polyfill": { 576 | "version": "3.3.3", 577 | "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", 578 | "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", 579 | "license": "MIT", 580 | "engines": { 581 | "node": ">= 8" 582 | } 583 | } 584 | } 585 | } 586 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "generatepost", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "scripts": { 6 | "start": "node index.js", 7 | "dev": "node --watch index.js", 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "type": "module", 14 | "description": "", 15 | "dependencies": { 16 | "axios": "^1.11.0", 17 | "dotenv": "^17.2.1", 18 | "form-data": "^4.0.4", 19 | "node-cron": "^4.2.1", 20 | "node-fetch": "^3.3.2", 21 | "replicate": "^1.0.1" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /service/generateArticle.js: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | import { config } from "../config/aiConfig.js"; 3 | 4 | export async function generateArticle(topic) { 5 | try { 6 | const response = await axios.post( 7 | "https://openrouter.ai/api/v1/chat/completions", 8 | { 9 | model: config.model, 10 | messages: [ 11 | { 12 | role: "user", 13 | content: `"${topic}" সম্পর্কে একটি বিস্তারিত বাংলা আর্টিকেল লিখুন (৩০০-৫০০ শব্দ)। গঠন: 14 | ১. আকর্ষণীয় শিরোনাম 15 | ২. ভূমিকা (সমস্যা বা প্রাসঙ্গিকতা) 16 | ৩. মূল বিষয়বস্তু (উপ-শিরোনাম সহ) 17 | ৪. ব্যবহারিক প্রয়োগ/উদাহরণ 18 | ৫. উপসংহার 19 | ৬. পাঠকদের জন্য প্রশ্ন`, 20 | }, 21 | ], 22 | max_tokens: 1500, 23 | temperature: 0.7, 24 | }, 25 | { headers: config.headers, timeout: 30000 } 26 | ); 27 | 28 | const article = response.data.choices[0]?.message?.content; 29 | return article; 30 | } catch (error) { 31 | console.error("Article generation failed:", error.message); 32 | throw new Error("Something went wrong to generate article"); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /service/generateImage.js: -------------------------------------------------------------------------------- 1 | import { config } from "../config/aiConfig.js"; 2 | 3 | export async function generateImage(data) { 4 | try { 5 | const response = await fetch( 6 | "https://router.huggingface.co/hf-inference/models/black-forest-labs/FLUX.1-dev", 7 | { 8 | method: "POST", 9 | headers: { 10 | Authorization: `Bearer ${config.huggingfaceApiKey}`, 11 | "Content-Type": "application/json", 12 | }, 13 | body: JSON.stringify(data), 14 | } 15 | ); 16 | 17 | if (!response.ok) { 18 | throw new Error(`HTTP ${response.status}: ${response.statusText}`); 19 | } 20 | 21 | const blob = await response.blob(); 22 | const arrayBuffer = await blob.arrayBuffer(); 23 | const buffer = Buffer.from(arrayBuffer); 24 | 25 | // Convert buffer to base64 26 | const base64Image = buffer.toString("base64"); 27 | 28 | // Upload to imgbb 29 | const uploadResponse = await fetch(`https://api.imgbb.com/1/upload?key=${config.imgbbApiKey}`, { 30 | method: "POST", 31 | headers: { 32 | "Content-Type": "application/x-www-form-urlencoded", 33 | }, 34 | body: new URLSearchParams({ 35 | image: base64Image, 36 | name: data.inputs || "generated_image" 37 | }), 38 | }); 39 | 40 | const uploadResult = await uploadResponse.json(); 41 | 42 | if (!uploadResponse.ok || !uploadResult.success) { 43 | throw new Error("Image upload failed"); 44 | } 45 | 46 | const imageUrl = uploadResult.data.url; 47 | return imageUrl; 48 | 49 | } catch (error) { 50 | console.error("Error generating/uploading image:", error.message); 51 | return null; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /service/generateTopic.js: -------------------------------------------------------------------------------- 1 | import { config } from "../config/aiConfig.js"; 2 | import axios from "axios"; 3 | 4 | 5 | export async function generateTopic() { 6 | try { 7 | const response = await axios.post( 8 | "https://openrouter.ai/api/v1/chat/completions", 9 | { 10 | model: config.model, 11 | messages: [{ 12 | role: "user", 13 | content: "Give me an interesting and recent topic related to programming, web development or web automation. (No extra explanation, just the topic name)" 14 | }], 15 | max_tokens: 50, 16 | temperature: 0.8 17 | }, 18 | { headers: config.headers } 19 | ); 20 | 21 | const topic = response.data.choices[0].message.content 22 | .replace(/["।]/g, '') 23 | .trim(); 24 | 25 | return topic; 26 | 27 | } catch (error) { 28 | console.error("Topic generation failed:", error.message); 29 | throw new Error("There are problem to generate topic"); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /utills/facebookPoster.js: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | import { config } from "../config/aiConfig.js"; 3 | 4 | export async function createPublicPost(article, image) { 5 | try { 6 | const endpoint = `https://graph.facebook.com/v23.0/${config.pageid}/photos?access_token=${config.fbAccessToken}`; 7 | 8 | const postData = { 9 | message: article, 10 | url: image, 11 | }; 12 | 13 | const response = await axios.post(endpoint, postData, { 14 | headers: { 15 | "Content-Type": "application/json", 16 | }, 17 | }); 18 | 19 | console.log("Facebook post response:", response.data); 20 | } catch (error) { 21 | console.error("Failed to post to Facebook.".error.message); 22 | 23 | if (error.response) { 24 | console.error( 25 | "Response data:", 26 | JSON.stringify(error.response.data, null, 2) 27 | ); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "builds": [ 4 | { 5 | "src": "index.js", 6 | "use": "@vercel/node" 7 | } 8 | ], 9 | "routes": [ 10 | { 11 | "src": "/(.*)", 12 | "dest": "/", 13 | "methods": ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"] 14 | } 15 | ] 16 | } --------------------------------------------------------------------------------