···11+import { BskyAgent } from "@atproto/api";
22+import * as dotenv from "dotenv"; // Added dotenv import
33+import { CronJob } from "cron";
44+import * as process from "process";
55+import { generateWolfNoiseString } from "./wolf-noise-generator"; // Import the function
66+77+// Load environment variables from the config.env file
88+dotenv.config({ path: "./config.env" });
99+1010+// Create a Bluesky Agent
1111+const agent = new BskyAgent({
1212+ service: "https://bsky.social",
1313+});
1414+1515+async function main() {
1616+ // Check for empty environment variables and abort if needed
1717+ if (!process.env.BLUESKY_USERNAME || !process.env.BLUESKY_PASSWORD) {
1818+ console.error(
1919+ "Missing required environment variables: BLUESKY_USERNAME and BLUESKY_PASSWORD. Aborting script."
2020+ );
2121+ return; // Exit the function if variables are empty
2222+ }
2323+2424+ try {
2525+ await agent.login({
2626+ identifier: process.env.BLUESKY_USERNAME!,
2727+ password: process.env.BLUESKY_PASSWORD!,
2828+ });
2929+3030+ // Generate a random wolf noise string
3131+ let randomNoise;
3232+ do {
3333+ randomNoise = generateWolfNoiseString();
3434+ } while (randomNoise.trim().length === 0); // Loop until a non-empty string is generated
3535+3636+ if (randomNoise) {
3737+ await agent.post({
3838+ text: randomNoise.trim(), // Use the generated string (trimmed)
3939+ langs: ["en-US"],
4040+ createdAt: new Date().toISOString(),
4141+ });
4242+ console.log("Just posted:", randomNoise.trim());
4343+ } else {
4444+ console.log("Failed to generate a valid wolf noise string after multiple attempts.");
4545+ }
4646+ } catch (error) {
4747+ console.error("Error during posting:", error);
4848+ // You can optionally implement retry logic or notify someone here
4949+ }
5050+}
5151+5252+main();
5353+5454+// Function to generate a random delay within 1-3 hours (in seconds)
5555+function getRandomDelay() {
5656+ const minHours = 1; // Minimum hours for delay
5757+ const maxHours = 3; // Maximum hours for delay
5858+5959+ // Convert hours to seconds
6060+ const minDelaySeconds = minHours * 60 * 60;
6161+ const maxDelaySeconds = maxHours * 60 * 60;
6262+6363+ // Generate a random number within the desired range (inclusive)
6464+ const randomDelay =
6565+ Math.floor(Math.random() * (maxDelaySeconds - minDelaySeconds + 1)) +
6666+ minDelaySeconds;
6767+6868+ return randomDelay;
6969+}
7070+7171+// Run this on a cron job
7272+const scheduleExpression = "0 * * * *"; // Every hour (used as a base for randomization)
7373+7474+const job = new CronJob(scheduleExpression, async () => {
7575+ const delay = getRandomDelay();
7676+ console.log(`Waiting for ${delay / 3600} hours before running main...`);
7777+ await new Promise((resolve) => setTimeout(resolve, delay * 1000)); // Wait for the random delay
7878+ main();
7979+});
8080+8181+job.start();
+53
wolf-noise-generator.ts
···11+import * as fs from "fs"; // File system module
22+33+// Function to getRandomInt
44+function getRandomInt(min: number, max: number): number {
55+ return Math.floor(Math.random() * (max - min + 1)) + min;
66+}
77+88+// Function to read the JSON data
99+function getWolfNoises(): {
1010+ howl: string[];
1111+ playful: string[];
1212+ scared: string[];
1313+ punctuation: { [category: string]: string[]; }; // Nested object for category-specific punctuation
1414+} {
1515+ try {
1616+ const data = fs.readFileSync("./wolf-noises.json", "utf-8");
1717+ return JSON.parse(data);
1818+ } catch (error) {
1919+ console.error("Error reading wolf-noises.json:", error);
2020+ throw error; // Re-throw the error for handling
2121+ }
2222+}
2323+2424+export function generateWolfNoiseString(): string {
2525+ const wolfNoises = getWolfNoises(); // Read JSON data
2626+ const category = getRandomInt(0, Object.keys(wolfNoises).length - 1); // Pick a random category key
2727+ const randomWords = wolfNoises[Object.keys(wolfNoises)[category]]; // Get words for that category
2828+2929+ let result = "";
3030+ let currentSentenceLength = 0;
3131+3232+ const maxLength = 280; // Set maximum length for the generated string
3333+3434+ while (result.length < maxLength) {
3535+ const randomWord = randomWords[getRandomInt(0, randomWords.length - 1)];
3636+ const wordLength = randomWord.length;
3737+3838+ // Check if adding the word exceeds the maximum length
3939+ if (result.length + wordLength <= maxLength) {
4040+ // Add a space if it's not the first word and result is not empty
4141+ if (result.length > 0) {
4242+ result += " ";
4343+ }
4444+ result += randomWord;
4545+ currentSentenceLength += wordLength;
4646+ } else {
4747+ // Break the loop if adding the word would exceed the maximum length
4848+ break;
4949+ }
5050+ }
5151+5252+ return result.trim(); // Remove any leading/trailing whitespace
5353+ }