Publish prototype for bot

Signed-off-by: Sam Therapy <sam@samtherapy.net>
This commit is contained in:
Sam Therapy 2022-01-05 17:45:53 -06:00
parent d922bb67ce
commit c97f1955de
Signed by: sam
GPG key ID: 4D8B07C18F31ACBD
5 changed files with 142 additions and 25 deletions

View file

@ -13,11 +13,9 @@ steps:
- name: build
image: node
commands:
- yarn
- yarn build
- name: test
image: node
commands:
- yarn
- yarn test

View file

@ -1,3 +1,48 @@
# fediverse-imagebot
A bot that posts images to the Fediverse
[![Build Status](https://ci.rint.osaka/api/badges/NotSam/fediverse-imagebot/status.svg)](https://ci.rint.osaka/NotSam/fediverse-imagebot)
A bot that posts images to the Fediverse.
Should be compatible with Mastodon, Misskey and Pleroma!
## Quick start guide
1. You need to have `npm` and `nodejs` installed.
2. Install `yarn`: \
`npm install --global yarn`
- This may be need to ran with `sudo` depending on your installation.
3. Clone the repository: \
`git clone https://git.freecumextremist.com/NotSam/fediverse-imagebot.git`
4. Install dependencies: \
`yarn`
5. Build: \
`yarn build`
6. Obtain a token. This can be done with an external tool or obtained by running `yarn token` and following the directions.
- `yarn token` will generate a configuration file located at `config.json`
7. Put images in the `images` folder.
- By default the bot will look for SFW images at `images/sfw` and NSFW images at `images/nsfw`. This can be configured.
8. Run the bot: \
`yarn bot`
You're done! The bot should post an image to the fediverse instance of your choosing!
## Automating the bot
*TODO: Elaborate more*
The bot can be automated to post images at set times using a cronjob. \
Example cron configuration:
```
0 * * * * cd /path/to/fediverse-imagebot && yarn bot -m "Message"
```
This example will run the bot every hour on the hour with the post message `Message`.
## Additional information
Additional help can be found by running `yarn bot -h` or `yarn token -h`.

View file

@ -12,14 +12,16 @@
},
"name": "fediverse-imagebot",
"version": "0.1.0",
"description": "Imagebot for the fediverse (Pleroma, Mastodon, Misskey)",
"description": "Image bot for the fediverse (Pleroma, Mastodon, Misskey)",
"main": "dist/bot.js",
"scripts": {
"build": "npm run clean && tsc",
"build": "yarn run clean && tsc",
"clean": "rm -rf dist",
"token": "node ./dist/gen-token.js",
"lint": "eslint --ext .ts src",
"test": "echo \"No tests yet!\" && exit 0",
"gen-token": "node ./dist/gen-token.js"
"bot": "node ./dist/bot.js",
"test": "echo \"No tests yet!\" && exit 0"
},
"repository": "https://git.freecumextremist.com/NotSam/fediverse-imagebot.git",
"author": "Sam Therapy <sam@samtherapy.net>",

View file

@ -1,6 +1,8 @@
#!/usr/bin/env node
import commandLineArgs from "command-line-args";
import commandLineUsage from "command-line-usage";
import * as fs from "fs";
import generator, { Entity, Response } from "megalodon";
import { exit } from "process";
@ -19,13 +21,37 @@ const optionDefinitions = [
description: "Print debugging output."
},
{
name: "directory",
name: "config",
type: String,
alias: "d",
description: "The directory of images for the bot to post.",
defaultValue: "./images",
typeLabel: "<files>"
alias: "c",
description: "Path to the configuration file.",
defaultValue: "./config.json",
typeLabel: "<file>"
},
{
name: "sfw_directory",
type: String,
alias: "s",
description: "The directory of (SFW) images for the bot to post.",
defaultValue: "./images/sfw",
typeLabel: "<folder>"
},
{
name: "nsfw_directory",
type: String,
alias: "n",
description: "The directory of (NSFW) images for the bot to post. If it chooses these, they will be marked sensitive.",
defaultValue: "./images/nsfw",
typeLabel: "<folder>"
},
{
name: "message",
type: String,
alias: "m",
description: "The message to post with the image.",
defaultValue: "",
typeLabel: "<message>"
}
];
const args = commandLineArgs(optionDefinitions);
@ -47,6 +73,53 @@ if (args.help) {
console.log(usage);
exit(0);
}
// JSON object read from config file
const data = JSON.parse(fs.readFileSync("./config.json", "utf8"));
console.log(data);
const sfw_files = fs.readdirSync(args.sfw_directory);
const nsfw_files = fs.readdirSync(args.nsfw_directory);
const random = Math.floor(Math.random() * (sfw_files.length + nsfw_files.length));
// Get image from directory and mark it as sensitive if it's in the nsfw directory
let image: fs.ReadStream;
let sensitive: boolean;
if (random >= sfw_files.length) {
// Random Image is NSFW, mark it sensitive
image = fs.createReadStream(args.nsfw_directory + "/" + nsfw_files[ random - sfw_files.length ]);
sensitive = true;
}
else {
// Image is SFW, mark it not sensitive
image = fs.createReadStream(args.sfw_directory + "/" + sfw_files[ random ]);
sensitive = false;
}
const client = generator(data.type, data.instance, data.accessToken);
client.uploadMedia(image).then((res: Response<Entity.Attachment>) => {
client.postStatus(args.message, {
media_ids: [ res.data.id ],
visibility: "unlisted",
sensitive: sensitive
}
).then((res: Response<Entity.Status>) => {
console.log("Successfully posted to " + data.instance);
if (args.verbose)
console.log(console.log(res.data));
exit(0);
}
).catch((err: Error) => {
console.error("Error posting to " + data.instance);
console.error("Run with -v to see the full error.");
if (args.verbose)
console.error(err);
exit(1);
}
);
}).catch((err: Error) => {
console.error("Error uploading image to " + data.instance);
console.error("Run with -v to see the full error.");
if (args.verbose)
console.error(err);
exit(1);
});

View file

@ -21,9 +21,7 @@ const optionDefinitions = [
description: "Print debugging output."
}
];
const args = commandLineArgs(optionDefinitions);
if (args.help) {
const usage = commandLineUsage([
{
@ -46,20 +44,23 @@ if (args.verbose) {
console.log("Running in verbose mode.");
console.log();
}
const instance: string = question("Instance URL: ");
callDetector(instance).then(type => {
let clientId!: string;
let clientSecret!: string;
const client = generator(type, instance);
client.registerApp("Node Imagebot", { scopes: [ "write" ] })
client.registerApp("Node Imagebot", { website: "https://git.freecumextremist.com/NotSam/fediverse-imagebot" })
.then((appData) => {
clientId = appData.clientId;
clientSecret = appData.clientSecret;
const clientId = appData.clientId;
const clientSecret = appData.clientSecret;
console.log("Please open this URL in your browser for the authorization code.");
console.log(appData.url);
const code = question("Authorization Code: ");
let code: string;
if (type === "misskey") {
code = appData.session_token || "";
question("Authenticate with Misskey, then hit return.");
} else {
code = question("Authorization Code: ");
}
client.fetchAccessToken(clientId, clientSecret, code)
.then((tokenData: OAuth.TokenData) => {
if (args.verbose) {
@ -82,7 +83,6 @@ callDetector(instance).then(type => {
console.error(err);
exit(1);
});
})
.catch((err: Error) => { // catch for registerApp
console.error("App registration failure!");
@ -92,7 +92,6 @@ callDetector(instance).then(type => {
});
});
async function callDetector(instance: string) {
const type = await detector(instance).catch( (err) => {
console.error("This does not seem to be a valid instance!");