Compare commits
No commits in common. "master" and "1.1.0" have entirely different histories.
|
@ -1,91 +0,0 @@
|
|||
local pipe(arch) = {
|
||||
kind: 'pipeline',
|
||||
type: 'docker',
|
||||
name: arch,
|
||||
platform: {
|
||||
arch: arch,
|
||||
},
|
||||
steps: [
|
||||
{
|
||||
name: 'deps',
|
||||
image: 'node',
|
||||
commands: [
|
||||
'corepack enable && pnpm config set store-dir .cache/pnpm',
|
||||
'pnpm i',
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'lint',
|
||||
image: 'node',
|
||||
commands: [
|
||||
'npm run lint:ci',
|
||||
],
|
||||
depends_on: [
|
||||
'deps',
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'build',
|
||||
image: 'node',
|
||||
commands: [
|
||||
'npm run build',
|
||||
],
|
||||
depends_on: [
|
||||
'lint',
|
||||
],
|
||||
},
|
||||
],
|
||||
trigger: {
|
||||
event: {
|
||||
exclude: [
|
||||
'tag',
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
local release(arch) = {
|
||||
kind: 'pipeline',
|
||||
type: 'docker',
|
||||
name: 'release-%s' % [arch],
|
||||
platform: {
|
||||
arch: arch,
|
||||
},
|
||||
trigger: {
|
||||
event: [
|
||||
'tag',
|
||||
],
|
||||
},
|
||||
steps: [
|
||||
{
|
||||
name: 'build',
|
||||
image: 'node:lts',
|
||||
commands: [
|
||||
'corepack enable && pnpm config set store-dir .cache/pnpm',
|
||||
'pnpm i',
|
||||
'pnpm build',
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'publish',
|
||||
image: 'plugins/npm',
|
||||
settings: {
|
||||
token: {
|
||||
from_secret: 'release_api_key',
|
||||
},
|
||||
registry: 'https://git.froth.zone/api/packages/sam/npm/',
|
||||
},
|
||||
depends_on: [
|
||||
'build',
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
[
|
||||
pipe('amd64'),
|
||||
pipe('arm64'),
|
||||
|
||||
release('amd64'),
|
||||
// release('arm64'),
|
||||
]
|
56
.drone.yml
Normal file
56
.drone.yml
Normal file
|
@ -0,0 +1,56 @@
|
|||
kind: pipeline
|
||||
type: docker
|
||||
name: default
|
||||
|
||||
steps:
|
||||
|
||||
- name: dependencies
|
||||
image: node
|
||||
commands:
|
||||
- yarn
|
||||
|
||||
- name: lint
|
||||
image: node
|
||||
depends_on:
|
||||
- dependencies
|
||||
commands:
|
||||
- yarn lint
|
||||
|
||||
- name: build
|
||||
image: node
|
||||
depends_on:
|
||||
- dependencies
|
||||
commands:
|
||||
- yarn build
|
||||
|
||||
- name: test
|
||||
image: node
|
||||
depends_on:
|
||||
- build
|
||||
commands:
|
||||
- yarn test
|
||||
|
||||
- name: package
|
||||
image: node
|
||||
depends_on:
|
||||
- lint
|
||||
- test
|
||||
commands:
|
||||
- yarn package
|
||||
when:
|
||||
event:
|
||||
- tag
|
||||
|
||||
- name: Release
|
||||
image: plugins/gitea-release
|
||||
depends_on:
|
||||
- package
|
||||
settings:
|
||||
api_key:
|
||||
from_secret: release_api_key
|
||||
base_url: https://git.froth.zone
|
||||
files:
|
||||
- dist/imagebot-*
|
||||
when:
|
||||
event:
|
||||
- tag
|
|
@ -1 +0,0 @@
|
|||
dist/
|
|
@ -1,24 +1,36 @@
|
|||
{
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es2021": true,
|
||||
"node": true
|
||||
},
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": "latest",
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": ["@typescript-eslint", "prettier"],
|
||||
"rules": {
|
||||
"linebreak-style": ["error", "unix"],
|
||||
"quotes": ["error", "double"],
|
||||
"semi": ["error", "never"],
|
||||
"prettier/prettier": ["error", { "singleQuote": false, "semi": false }]
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:prettier/recommended"
|
||||
]
|
||||
"env": {
|
||||
"commonjs": true,
|
||||
"es2021": true,
|
||||
"node": true
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended"
|
||||
],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 13
|
||||
},
|
||||
"plugins": [
|
||||
"@typescript-eslint"
|
||||
],
|
||||
"rules": {
|
||||
"indent": [
|
||||
"error",
|
||||
4
|
||||
],
|
||||
"linebreak-style": [
|
||||
"error",
|
||||
"unix"
|
||||
],
|
||||
"quotes": [
|
||||
"error",
|
||||
"double"
|
||||
],
|
||||
"semi": [
|
||||
"error",
|
||||
"always"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
14
.gitignore
vendored
14
.gitignore
vendored
|
@ -112,15 +112,11 @@ dist
|
|||
.vscode-test
|
||||
|
||||
# yarn v2
|
||||
.yarn/*
|
||||
!.yarn/cache
|
||||
!.yarn/releases
|
||||
!.yarn/plugins
|
||||
!.yarn/sdks
|
||||
!.yarn/versions
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
.dccache
|
||||
config.json
|
||||
config.jsonc
|
||||
config.json5
|
||||
images/*
|
|
@ -1,2 +0,0 @@
|
|||
dist/
|
||||
.yarn/
|
17
LICENSE
17
LICENSE
|
@ -1,10 +1,9 @@
|
|||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted.
|
||||
MIT License
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
Copyright (c) 2022 Sam Therapy
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
|
93
README.md
93
README.md
|
@ -1,87 +1,50 @@
|
|||
# fediverse-imagebot
|
||||
|
||||
[![Build Status](https://ci.git.froth.zone/api/badges/sam/fediverse-imagebot/status.svg)](https://ci.git.froth.zone/sam/fediverse-imagebot)
|
||||
[![Build Status](https://ci.git.froth.zone/api/badges/Sam/fediverse-imagebot/status.svg)](https://ci.git.froth.zone/Sam/fediverse-imagebot)
|
||||
|
||||
A bot that posts local and booru images to the Fediverse.
|
||||
A bot that posts (currently only local) images to the Fediverse.
|
||||
|
||||
Compatible with Mastodon, Misskey and Pleroma!
|
||||
|
||||
## MIGRATING MAJOR VERSIONS
|
||||
|
||||
See [the wiki](https://git.froth.zone/sam/fediverse-imagebot/wiki/Migrating).
|
||||
|
||||
## Boorus supported
|
||||
|
||||
The full list of boorus supported is found [here](https://github.com/AtoraSuunva/booru/blob/master/src/sites.json).
|
||||
|
||||
## Downloading the bot
|
||||
|
||||
There are currently three ways to do this, a pre-built binary that bundles in node, from npm, or building from source. Both are listed below.
|
||||
|
||||
### From NPM
|
||||
|
||||
1. Set up using the [Gitea registry](https://git.froth.zone/sam/fediverse-imagebot/packages)
|
||||
|
||||
```sh
|
||||
npm config set @froth:registry https://git.froth.zone/api/packages/sam/npm/
|
||||
```
|
||||
|
||||
2. After setting up the registry, either run it once
|
||||
|
||||
```sh
|
||||
npx --package=@froth/fediverse-imagebot fediverse-imagebot
|
||||
```
|
||||
|
||||
or install globally
|
||||
|
||||
```sh
|
||||
npm i -g @froth/fediverse-imagebot
|
||||
```
|
||||
|
||||
### Downloading pre-built binaries
|
||||
|
||||
#### NOTE: This is no longer supported since vercel/pkg is broken
|
||||
|
||||
Download prebuilt binaries from [here](https://git.froth.zone/sam/fediverse-imagebot/releases/latest). (currently supports x86_64 and arm64 on Linux
|
||||
[glibc or musl], macOS and Windows)
|
||||
|
||||
1. Run the bot with the `-w` flag to have it generate a configuration file to the local directory.
|
||||
2. Edit it for your use case.
|
||||
- If you want to generate a key you can use <https://git.froth.zone/sam/js-feditoken>
|
||||
3. Run the bot by launching the executable!
|
||||
|
||||
### Running from Source
|
||||
## Downloading pre-built binaries
|
||||
Download prebuilt binaries from [here](https://git.froth.zone/Sam/fediverse-imagebot/releases/latest) (currently only supports x64), or build from source, instructions below.
|
||||
|
||||
## Running from Source
|
||||
1. You need to have `npm` and `nodejs` installed.
|
||||
- Node 16 or greater is required.
|
||||
2. Install `pnpm`: \
|
||||
`corepack enable` \
|
||||
Check <https://pnpm.io/installation> for more information.
|
||||
- Node 15 or greater is required.
|
||||
|
||||
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.froth.zone/sam/fediverse-imagebot.git`
|
||||
`git clone https://git.freecumextremist.com/NotSam/fediverse-imagebot.git`
|
||||
|
||||
4. Install dependencies: \
|
||||
`pnpm i`
|
||||
`yarn --production`
|
||||
|
||||
5. Build: \
|
||||
`pnpm run build`
|
||||
6. Edit the config file: \
|
||||
`cp config.sample.jsonc config.jsonc`
|
||||
- If you want to generate a key you can use https://git.froth.zone/sam/js-feditoken
|
||||
7. Run the bot: \
|
||||
`pnpm bot`
|
||||
`yarn build`
|
||||
|
||||
8. Run the bot: \
|
||||
`yarn local`
|
||||
|
||||
You're done! The bot should post a local image to the fediverse instance of your choosing!
|
||||
|
||||
## Automating the bot
|
||||
## Running the bot
|
||||
1. Obtain a token. I have another tool that does this for you, which can be found [here](https://git.froth.zone/Sam/js-feditoken) and put it in `config.json`, following the sample json file.
|
||||
|
||||
_TODO: Elaborate more_
|
||||
2. 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 with the `-d` flag.
|
||||
|
||||
## 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 && pnpm bot -c ./config.sample.jsonc
|
||||
0 * * * * cd /path/to/fediverse-imagebot && /usr/local/bin/yarn local -m "Message"
|
||||
```
|
||||
|
||||
This example will run the bot every hour on the hour with no message using images from the default `images` directory.
|
||||
This example will run the bot every hour on the hour with the post message `Message` using images from the default `images` directory.
|
||||
|
||||
An example of this pleroma configuration can be found at https://froth.zone/rinbot.
|
||||
|
|
|
@ -1,33 +1,8 @@
|
|||
// This is just a mock of what the config should look like
|
||||
// Run yarn build && yarn gen-token to generate the configuration.
|
||||
{
|
||||
//Instance and token settings
|
||||
"instance": "INSTANCE_URL", // example https://test.com
|
||||
"type": "INSTANCE_TYPE", // examples: "mastodon", "misskey", "pleroma"
|
||||
"accessToken": "ACCESS_TOKEN", // Get a token from https://git.froth.zone/Sam/js-feditoken
|
||||
"refreshToken": "REFRESH_TOKEN", // optional
|
||||
|
||||
// Post settings
|
||||
"message": "", // example: "Hello, world!"
|
||||
"visibility": "unlisted", // example: "public", "unlisted", "private", "direct"
|
||||
|
||||
// Misc settings
|
||||
"retries": 5, // Number of times to retry an upload/post if it fails. Default is 5 if this does not exist.
|
||||
|
||||
"remote": false, // **Set this to `true` if you want to serve a file from a booru!**
|
||||
/* THESE SETTINGS WILL BE IGNORED IF YOU SET `remote` TO `false` */
|
||||
"booru": "safebooru.org", // example: "safebooru.org"
|
||||
"tags": [""], // example: ["tohsaka_rin", "-feet"]
|
||||
"rating": "safe", // example: "safe", "questionable", "explicit"
|
||||
/* END OF SETTINGS THAT WILL BE IGNORED IF YOU SET `remote` TO `false` */
|
||||
|
||||
/* THESE SETTINGS WILL BE IGNORED IF YOU SET `remote` TO `true` */
|
||||
"directory": "./images" // example: "./images"
|
||||
/*
|
||||
Directory structure should be as follows:
|
||||
folder/
|
||||
- sfw/
|
||||
- image1.jpg
|
||||
- nsfw/
|
||||
- image1.jpg
|
||||
*/
|
||||
/* END OF SETTINGS THAT WILL BE IGNORED IF YOU SET `remote` TO `true` */
|
||||
}
|
||||
"accessToken": "ACCESS_TOKEN",
|
||||
"refreshToken": "REFRESH_TOKEN" // This can be left blank, as it is currently not used for anything.
|
||||
}
|
84
package.json
84
package.json
|
@ -1,53 +1,37 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"booru": "2.6.3",
|
||||
"command-line-args": "5.2.1",
|
||||
"command-line-usage": "7.0.1",
|
||||
"got": "12.6.1",
|
||||
"json5": "2.2.3",
|
||||
"megalodon": "6.0.2",
|
||||
"p-retry": "5.1.2"
|
||||
},
|
||||
"name": "@froth/fediverse-imagebot",
|
||||
"version": "2.1.1",
|
||||
"description": "Image bot for the fediverse (Pleroma, Mastodon, Misskey)",
|
||||
"main": "dist/bot.js",
|
||||
"bin": "dist/bot.js",
|
||||
"pkg": {
|
||||
"scripts": "dist/**/*.js"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc -b",
|
||||
"clean": "tsc -b --clean",
|
||||
"lint": "eslint --ext .ts ./src --fix && prettier --no-semi --write ./src",
|
||||
"lint:ci": "eslint --ext .ts,.js ./src && prettier --no-semi --check ./src",
|
||||
"bot": "node ./dist/bot.js",
|
||||
"package": "pkg . -C Gzip",
|
||||
"test": "echo \"No tests yet!\" && exit 0",
|
||||
"prepublishOnly": "npm run build"
|
||||
},
|
||||
"repository": "https://git.froth.zone/sam/fediverse-imagebot",
|
||||
"author": "Sam Therapy <sam@samtherapy.net>",
|
||||
"license": "0BSD",
|
||||
"devDependencies": {
|
||||
"@types/command-line-args": "5.2.0",
|
||||
"@types/command-line-usage": "5.0.2",
|
||||
"@types/http-cache-semantics": "4.0.1",
|
||||
"@types/node": "18.16.16",
|
||||
"@typescript-eslint/eslint-plugin": "5.59.7",
|
||||
"@typescript-eslint/parser": "5.59.7",
|
||||
"eslint": "8.41.0",
|
||||
"eslint-config-prettier": "8.8.0",
|
||||
"eslint-plugin-prettier": "4.2.1",
|
||||
"pkg": "5.8.1",
|
||||
"prettier": "2.8.8",
|
||||
"typescript": "5.0.4"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"type": "module",
|
||||
"publishConfig": {
|
||||
"registry": "https://git.froth.zone/api/packages/sam/npm/"
|
||||
"dependencies": {
|
||||
"command-line-args": "^5.2.1",
|
||||
"command-line-usage": "^6.1.1",
|
||||
"megalodon": "^4.0.0",
|
||||
"typescript": "^4.5.5"
|
||||
},
|
||||
"name": "fediverse-imagebot",
|
||||
"version": "1.1.0",
|
||||
"description": "Image bot for the fediverse (Pleroma, Mastodon, Misskey)",
|
||||
"main": "dist/local.js",
|
||||
"bin": "dist/local.js",
|
||||
"pkg": {
|
||||
"scripts": "build/**/*.js",
|
||||
"targets": ["node16-linux-x64","node16-macos-x64","node16-win-x64"]
|
||||
},
|
||||
"scripts": {
|
||||
"build": "yarn run clean && tsc",
|
||||
"clean": "rm -rf dist",
|
||||
"lint": "eslint --ext .ts src",
|
||||
"local": "node ./dist/local.js",
|
||||
"package": "pkg . -o dist/imagebot-x64 -C Gzip",
|
||||
"test": "echo \"No tests yet!\" && exit 0"
|
||||
},
|
||||
"repository": "https://git.froth.zone/Sam/fediverse-imagebot",
|
||||
"author": "Sam Therapy <sam@samtherapy.net>",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@types/command-line-args": "^5.2.0",
|
||||
"@types/command-line-usage": "^5.0.2",
|
||||
"@types/node": "^17.0.18",
|
||||
"@typescript-eslint/eslint-plugin": "^5.12.0",
|
||||
"@typescript-eslint/parser": "^5.12.0",
|
||||
"eslint": "^8.9.0",
|
||||
"pkg": "^5.5.2"
|
||||
}
|
||||
}
|
||||
|
|
2051
pnpm-lock.yaml
2051
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": ["config:base"],
|
||||
"rangeStrategy": "pin"
|
||||
}
|
23
src/bot.ts
23
src/bot.ts
|
@ -1,23 +0,0 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
import getLocalImage from "./getLocalImage.js"
|
||||
import getRemoteImage from "./getRemoteImage.js"
|
||||
import getConfig from "./helpers/getConfig.js"
|
||||
import { config } from "./helpers/types.js"
|
||||
|
||||
/**
|
||||
* Main function
|
||||
*/
|
||||
async function main() {
|
||||
const conf: config = await getConfig()
|
||||
|
||||
if (conf.remote) await getRemoteImage(conf)
|
||||
else await getLocalImage(conf)
|
||||
}
|
||||
|
||||
if (Number(process.versions.node.split(".")[0]) < 16) {
|
||||
console.error("Please upgrade to node 16. NO GUARENTEES!")
|
||||
}
|
||||
|
||||
// Run the main function, obviously.
|
||||
main()
|
|
@ -1,62 +0,0 @@
|
|||
import { createReadStream, ReadStream } from "node:fs"
|
||||
import { readdir } from "node:fs/promises"
|
||||
import { exit } from "node:process"
|
||||
|
||||
import postImage from "./postImage.js"
|
||||
import args from "./helpers/args.js"
|
||||
import crashHandler from "./helpers/crashHandler.js"
|
||||
import { config } from "./helpers/types.js"
|
||||
|
||||
/**
|
||||
* Get a local image from the filesystem
|
||||
* @param conf Configuration object (see {@link config})
|
||||
* @calls postImage with the image it randomly selects from the local directory
|
||||
*/
|
||||
export default async function getLocalImage(conf: config) {
|
||||
// Get SFW directory
|
||||
const sfw_files: string[] = await readdir(`${conf.directory}/sfw`).catch(
|
||||
(e) => {
|
||||
crashHandler("Error reading SFW image directory.", e)
|
||||
return []
|
||||
}
|
||||
)
|
||||
// Get NSFW directory
|
||||
const nsfw_files: string[] = await readdir(`${conf.directory}/nsfw`).catch(
|
||||
(e) => {
|
||||
crashHandler("Error reading NSFW image directory.", e)
|
||||
return []
|
||||
}
|
||||
)
|
||||
const random = Math.floor(
|
||||
Math.random() * (sfw_files.length + nsfw_files.length)
|
||||
)
|
||||
|
||||
// Filler that is used to get a random file from the directories
|
||||
let image: ReadStream
|
||||
let sensitivity: boolean
|
||||
let file: string
|
||||
|
||||
if (random >= sfw_files.length) {
|
||||
// Image is NSFW, mark it sensitive
|
||||
file = `${conf.directory}/nsfw/${nsfw_files[random - sfw_files.length]}`
|
||||
image = createReadStream(file).on("error", (err: Error) => {
|
||||
crashHandler(`Error reading file "${file}"`, err)
|
||||
})
|
||||
sensitivity = true
|
||||
} else {
|
||||
// Image is SFW, mark it not sensitive
|
||||
file = `${conf.directory}/sfw/${sfw_files[random]}`
|
||||
image = createReadStream(file).on("error", (err: Error) => {
|
||||
crashHandler(`Error reading file "${file}"`, err)
|
||||
})
|
||||
sensitivity = false
|
||||
}
|
||||
|
||||
if (args.verbose) {
|
||||
console.log(`File being sent: ${file}`)
|
||||
console.log(`Sensitivity: ${sensitivity}`)
|
||||
}
|
||||
|
||||
await postImage(image, sensitivity, conf)
|
||||
exit(0)
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
import { createReadStream, createWriteStream } from "node:fs"
|
||||
import { unlink } from "node:fs/promises"
|
||||
import { exit } from "node:process"
|
||||
import stream from "node:stream"
|
||||
import { promisify } from "node:util"
|
||||
|
||||
import { search, Post } from "booru"
|
||||
import got from "got"
|
||||
|
||||
import postImage from "./postImage.js"
|
||||
import args from "./helpers/args.js"
|
||||
import crashHandler from "./helpers/crashHandler.js"
|
||||
import { config } from "./helpers/types.js"
|
||||
|
||||
/**
|
||||
* Get a remote image from a booru
|
||||
*
|
||||
* Currently this also downloads the image locally but idc nmp it gets deleted
|
||||
* @param conf Configuration object (see {@link config})
|
||||
* @calls postImage with the image it randomly selects from the booru given
|
||||
*/
|
||||
export default async function getRemoteImage(conf: config) {
|
||||
const searchResults = await search(conf.booru, conf.tags, {
|
||||
limit: 1,
|
||||
random: true,
|
||||
}).catch((e) => {
|
||||
crashHandler("Error searching for posts.", e)
|
||||
return [] as Post[]
|
||||
})
|
||||
if (searchResults.length === 0) {
|
||||
crashHandler("Error searching for posts.", Error("No posts found."))
|
||||
return
|
||||
}
|
||||
const post = searchResults[0]
|
||||
if (args.verbose) console.log(`Found post: ${post.id} at ${post.file_url}`)
|
||||
// Set the post as sensitive if the rating is not safe
|
||||
const sensitivity: boolean = post.rating !== "s"
|
||||
// Make an HTTP request for the image
|
||||
const filename: string = post.fileUrl?.split("/").pop() as string // Type checks for type checks
|
||||
const pipeline = promisify(stream.pipeline)
|
||||
|
||||
// Make the HTTP request as a stream so it can be piped to the file system
|
||||
await pipeline(
|
||||
got.stream(post.file_url as string),
|
||||
createWriteStream(filename)
|
||||
).catch((err: Error) => {
|
||||
crashHandler("Error saving downloading image.", err)
|
||||
})
|
||||
if (args.verbose) console.log(`Saved image to ${filename}`)
|
||||
const str = createReadStream(filename).on("error", (err: Error) => {
|
||||
crashHandler("Error reading downloaded image.", err)
|
||||
})
|
||||
|
||||
if (args.verbose) {
|
||||
console.log(`File being sent: ${filename}\nSensitivity: ${sensitivity}`)
|
||||
}
|
||||
// Make a status with the image
|
||||
await postImage(str, sensitivity, conf)
|
||||
|
||||
// Delete the image that it downloaded
|
||||
await unlink(filename).catch((err: Error) => {
|
||||
crashHandler("Error deleting downloaded image.", err)
|
||||
})
|
||||
if (args.verbose) console.log(`Successfully deleted image ${filename}`)
|
||||
exit(0)
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
import { exit } from "node:process"
|
||||
|
||||
import commandLineArgs from "command-line-args"
|
||||
import commandLineUsage from "command-line-usage"
|
||||
import writeConfig from "./writeConfig.js"
|
||||
|
||||
const optionDefinitions = [
|
||||
{
|
||||
name: "help",
|
||||
type: Boolean,
|
||||
alias: "h",
|
||||
description: "Print this usage guide.",
|
||||
},
|
||||
{
|
||||
name: "verbose",
|
||||
type: Boolean,
|
||||
alias: "v",
|
||||
defaultValue: false,
|
||||
description: "Print debugging output.",
|
||||
},
|
||||
{
|
||||
name: "config",
|
||||
type: String,
|
||||
alias: "c",
|
||||
description:
|
||||
"Path to the JSON configuration file. (default: ./config.jsonc)",
|
||||
defaultValue: "./config.jsonc",
|
||||
typeLabel: "<file.json[c,5]>",
|
||||
},
|
||||
{
|
||||
name: "writeConfig",
|
||||
type: Boolean,
|
||||
alias: "w",
|
||||
description:
|
||||
"Write a default configuration file to the current directory and exit.",
|
||||
},
|
||||
{
|
||||
name: "message",
|
||||
type: String,
|
||||
alias: "m",
|
||||
description: "The message to post with the image.",
|
||||
defaultValue: "",
|
||||
typeLabel: "<message>",
|
||||
},
|
||||
]
|
||||
|
||||
const args = commandLineArgs(optionDefinitions)
|
||||
|
||||
if (args.help) {
|
||||
const usage = commandLineUsage([
|
||||
{
|
||||
header: "Fediverse Image Bot",
|
||||
content:
|
||||
"A bot that posts images from a local directory to the Fediverse.",
|
||||
},
|
||||
{
|
||||
header: "Options",
|
||||
optionList: optionDefinitions,
|
||||
},
|
||||
{
|
||||
content:
|
||||
"Project home: {underline https://git.froth.zone/Sam/fediverse-imagebot}",
|
||||
},
|
||||
])
|
||||
console.log(usage)
|
||||
exit(0)
|
||||
}
|
||||
|
||||
if (args.verbose) console.log("Running in verbose mode.\n")
|
||||
|
||||
if (args.writeConfig) {
|
||||
writeConfig(args.verbose).then(() => {
|
||||
console.log("Wrote default config file to ./config.jsonc")
|
||||
exit(0)
|
||||
})
|
||||
}
|
||||
|
||||
export default args
|
69
src/helpers/cli.ts
Normal file
69
src/helpers/cli.ts
Normal file
|
@ -0,0 +1,69 @@
|
|||
import commandLineArgs from "command-line-args";
|
||||
import commandLineUsage from "command-line-usage";
|
||||
import { exit } from "process";
|
||||
|
||||
const optionDefinitions = [
|
||||
{
|
||||
name: "help",
|
||||
type: Boolean,
|
||||
alias: "h",
|
||||
description: "Print this usage guide."
|
||||
},
|
||||
{
|
||||
name: "verbose",
|
||||
type: Boolean,
|
||||
alias: "v",
|
||||
description: "Print debugging output."
|
||||
},
|
||||
{
|
||||
name: "config",
|
||||
type: String,
|
||||
alias: "c",
|
||||
description: "Path to the JSON configuration file. (default: ./config.json)",
|
||||
defaultValue: "./config.json",
|
||||
typeLabel: "<file.json>"
|
||||
},
|
||||
{
|
||||
name: "directory",
|
||||
type: String,
|
||||
alias: "d",
|
||||
description: "The directory of images to upload. (default: ./images)",
|
||||
defaultValue: "./images",
|
||||
typeLabel: "<folder>"
|
||||
},
|
||||
{
|
||||
name: "message",
|
||||
type: String,
|
||||
alias: "m",
|
||||
description: "The message to post with the image.",
|
||||
defaultValue: "",
|
||||
typeLabel: "<message>"
|
||||
}
|
||||
];
|
||||
|
||||
const args = commandLineArgs(optionDefinitions);
|
||||
|
||||
if (args.help) {
|
||||
const usage = commandLineUsage([
|
||||
{
|
||||
header: "Fediverse Image Bot",
|
||||
content: "A bot that posts images from a local directory to the Fediverse."
|
||||
},
|
||||
{
|
||||
header: "Options",
|
||||
optionList: optionDefinitions
|
||||
},
|
||||
{
|
||||
content: "Project home: {underline https://git.froth.zone/Sam/fediverse-imagebot}"
|
||||
}
|
||||
]);
|
||||
console.log(usage);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (args.verbose) {
|
||||
console.log("Running in verbose mode.\n");
|
||||
}
|
||||
|
||||
|
||||
export default args;
|
20
src/helpers/config.ts
Normal file
20
src/helpers/config.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
import args from "./cli";
|
||||
import crashHandler from "./errors";
|
||||
import { readFile } from "fs/promises";
|
||||
|
||||
// Read the config file and return the contents as a JSON object
|
||||
export default async function config() {
|
||||
try {
|
||||
return JSON.parse(
|
||||
await readFile(args.config, "utf8")
|
||||
.catch(err => {
|
||||
crashHandler("Error reading config file.", err);
|
||||
return ("");
|
||||
})
|
||||
);
|
||||
}
|
||||
catch (e: unknown) {
|
||||
crashHandler("Error reading config file.", e);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
import { exit } from "node:process"
|
||||
|
||||
import args from "./args.js"
|
||||
|
||||
/**
|
||||
* The function that gets called when the program runs into an error.
|
||||
* @param msg Custom error message
|
||||
* @param e Error object passed in from the error handler
|
||||
* @returns This function will never return.
|
||||
*/
|
||||
export default function crashHandler(msg: string, e: Error, res?: string) {
|
||||
console.error(`${msg}: ${e.name}`)
|
||||
if (args.verbose) {
|
||||
console.error(`--BEGIN FULL ERROR--\n${e}\n${res}\n--END FULL ERROR--`)
|
||||
} else console.error("Run with -v to see the full error.")
|
||||
|
||||
exit(1)
|
||||
}
|
13
src/helpers/errors.ts
Normal file
13
src/helpers/errors.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
import { exit } from "process";
|
||||
import args from "./cli";
|
||||
|
||||
// Boilerplate for the event any error occurs
|
||||
export default function crashHandler(msg: string, e: Error | unknown) {
|
||||
console.error(msg);
|
||||
if (args.verbose) {
|
||||
console.error(`--BEGIN FULL ERROR--\n${e}\n--END FULL ERROR--`);
|
||||
} else
|
||||
console.error("Run with -v to see the full error.");
|
||||
|
||||
exit(1);
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
import { readFile } from "node:fs/promises"
|
||||
|
||||
import JSON5 from "json5"
|
||||
|
||||
import args from "./args.js"
|
||||
import crashHandler from "./crashHandler.js"
|
||||
import { config } from "./types.js"
|
||||
|
||||
/**
|
||||
* Reads the config file and returns the config object
|
||||
* @returns The config object
|
||||
*/
|
||||
async function readConfig(): Promise<string> {
|
||||
return readFile(args.config, "utf8").catch((err) => {
|
||||
crashHandler("Error reading config file.", err)
|
||||
return "CRASH"
|
||||
})
|
||||
}
|
||||
/**
|
||||
* Parses the config file and returns it as a JSON object
|
||||
*
|
||||
* See config.sample.jsonc for an example of the config file
|
||||
* @returns {Promise<config>} The config file as a JSON object(see {@link config})
|
||||
* @example
|
||||
* const cfg = await getConfig();
|
||||
* console.log(cfg.instance);
|
||||
* // Prints "https://mastodon.social"
|
||||
*/
|
||||
export default async function getConfig(): Promise<config> {
|
||||
let conf: config
|
||||
try {
|
||||
conf = JSON5.parse(
|
||||
await readConfig().catch((err) => {
|
||||
crashHandler("Error reading config file.", err)
|
||||
return ""
|
||||
})
|
||||
)
|
||||
// Backwards compatibility for older versions
|
||||
conf.retries ??= 5
|
||||
if (conf.retries < 1) conf.retries = 1
|
||||
} catch (err: unknown) {
|
||||
crashHandler("Error parsing config file.", Error(err as string))
|
||||
return {} as config
|
||||
}
|
||||
if (args.verbose) {
|
||||
console.log(`Read config file: ${args.config}\n${JSON.stringify(conf)}`)
|
||||
}
|
||||
return conf
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
/**
|
||||
* Config type to reduce boilerplate
|
||||
*/
|
||||
export type config = {
|
||||
instance: string
|
||||
type: "misskey" | "mastodon" | "pleroma"
|
||||
accessToken: string
|
||||
refreshToken: string | null
|
||||
message: string
|
||||
visibility: "direct" | "unlisted" | "private" | "public"
|
||||
remote: boolean
|
||||
booru: string
|
||||
tags: string[]
|
||||
directory: string
|
||||
retries: number
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
import { writeFile } from "node:fs/promises"
|
||||
/**
|
||||
* Writes the sample config file to disk
|
||||
* @returns Nothing
|
||||
*/
|
||||
export default async function writeConfig(verbose: boolean) {
|
||||
if (verbose) console.log("Writing sample config to config.jsonc")
|
||||
await writeFile(
|
||||
"./config.jsonc",
|
||||
// eslint-disable-next-line prettier/prettier
|
||||
// prettier-ignore
|
||||
"{ \n //Instance and token settings \n \"instance\": \"INSTANCE_URL\", // example https://test.com \n \"type\": \"INSTANCE_TYPE\", // examples: \"mastodon\", \"misskey\", \"pleroma\" \n \"accessToken\": \"ACCESS_TOKEN\", // Get a token from https://git.froth.zone/Sam/js-feditoken \n \"refreshToken\": \"REFRESH_TOKEN\", // optional \n \n // Post settings \n \"message\": \"\", // example: \"Hello, world!\" \n \"visibility\": \"unlisted\", // example: \"public\", \"unlisted\", \"private\", \"direct\" \n \n \"remote\": false, // **Set this to `true` if you want to serve a file from a booru!** \n /* THESE SETTINGS WILL BE IGNORED IF YOU SET `remote` TO `false` */ \n \"booru\": \"safebooru.org\", // example: \"safebooru.org\" \n \"tags\": [\"\"], // example: [\"tohsaka_rin\", \"-feet\"] \n \"rating\": \"safe\", // example: \"safe\", \"questionable\", \"explicit\" \n /* END OF SETTINGS THAT WILL BE IGNORED IF YOU SET `remote` TO `false` */ \n \n /* THESE SETTINGS WILL BE IGNORED IF YOU SET `remote` TO `true` */ \n \"directory\": \"./images\" // example: \"./images\" \n /* \n Directory structure should be as follows: \n folder/ \n - sfw/ \n - image1.jpg \n - nsfw/ \n - image1.jpg \n */ \n /* END OF SETTINGS THAT WILL BE IGNORED IF YOU SET `remote` TO `true` */ \n} \n"
|
||||
)
|
||||
}
|
53
src/local.ts
Normal file
53
src/local.ts
Normal file
|
@ -0,0 +1,53 @@
|
|||
import { createReadStream, ReadStream } from "fs";
|
||||
import { readdir } from "fs/promises";
|
||||
import { exit } from "process";
|
||||
|
||||
import args from "./helpers/cli";
|
||||
import crashHandler from "./helpers/errors";
|
||||
import post from "./post";
|
||||
|
||||
export default async function getLocalImage() {
|
||||
const sfw_files: string[] = await readdir(`${args.directory}/sfw`).catch(e => {
|
||||
crashHandler("Error reading SFW image directory.", e);
|
||||
return [];
|
||||
});
|
||||
const nsfw_files: string[] = await readdir(`${args.directory}/nsfw`).catch(e => {
|
||||
crashHandler("Error reading NSFW image directory.", e);
|
||||
return [];
|
||||
});
|
||||
const random = Math.floor(Math.random() * (sfw_files.length + nsfw_files.length));
|
||||
|
||||
// Filler that is used to get a random file from the directories
|
||||
let image: ReadStream;
|
||||
let sensitivity: boolean;
|
||||
let file = "";
|
||||
|
||||
if (random >= sfw_files.length) {
|
||||
// Image is NSFW, mark it sensitive
|
||||
file = `${args.directory}/nsfw/${nsfw_files[ random - sfw_files.length ]}`;
|
||||
image = createReadStream(file)
|
||||
.on("error", (err: Error) => {
|
||||
crashHandler(`Error reading file "${file}"`, err);
|
||||
});
|
||||
sensitivity = true;
|
||||
}
|
||||
else {
|
||||
// Image is SFW, mark it not sensitive
|
||||
file = `${args.directory}/sfw/${sfw_files[ random]}`;
|
||||
image = createReadStream(file)
|
||||
.on("error", (err: Error) => {
|
||||
crashHandler(`Error reading file "${file}"`, err);
|
||||
});
|
||||
sensitivity = false;
|
||||
}
|
||||
|
||||
if (args.verbose) {
|
||||
console.error(`File being sent: ${file}`);
|
||||
console.error(`Sensitivity: ${sensitivity}`);
|
||||
}
|
||||
|
||||
await post(image, sensitivity);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
getLocalImage();
|
43
src/post.ts
Normal file
43
src/post.ts
Normal file
|
@ -0,0 +1,43 @@
|
|||
import { ReadStream } from "fs";
|
||||
import generator, { Entity, Response } from "megalodon";
|
||||
|
||||
import config from "./helpers/config";
|
||||
import crashHandler from "./helpers/errors";
|
||||
import args from "./helpers/cli";
|
||||
|
||||
// Uploads an image to the Fediverse
|
||||
// image: The image to upload
|
||||
// sensitivity: Whether or not the image is sensitive
|
||||
export default async function post(image: ReadStream, sensitivity: boolean) {
|
||||
// Get config
|
||||
const cfg: {
|
||||
instance: string,
|
||||
type: "misskey" | "mastodon" | "pleroma",
|
||||
accessToken: string,
|
||||
refreshToken: string | null
|
||||
} = await config();
|
||||
|
||||
// Make a client to upload
|
||||
const client = generator(cfg.type, cfg.instance, cfg.accessToken, cfg.refreshToken);
|
||||
|
||||
// Upload the image
|
||||
const res: Response<Entity.Attachment> = await client.uploadMedia(image).catch(err => {
|
||||
crashHandler("Error uploading image.", err);
|
||||
return ({} as Response<Entity.Attachment>);
|
||||
});
|
||||
|
||||
// Make a status with the image
|
||||
await client.postStatus(args.message,
|
||||
{
|
||||
media_ids: [ res.data.id ],
|
||||
// Change this to make the post visibility you wish
|
||||
visibility: "unlisted",
|
||||
sensitive: sensitivity
|
||||
}
|
||||
).catch(err => {
|
||||
crashHandler("Error posting status.", err);
|
||||
});
|
||||
if (args.verbose)
|
||||
console.log(`Successfully posted to ${cfg.instance}`);
|
||||
return;
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
import { ReadStream } from "node:fs"
|
||||
import { Readable } from "node:stream"
|
||||
|
||||
import generatorPkg, { Entity, Response } from "megalodon"
|
||||
const generator = generatorPkg.default
|
||||
|
||||
import pRetry from "p-retry"
|
||||
|
||||
import args from "./helpers/args.js"
|
||||
import crashHandler from "./helpers/crashHandler.js"
|
||||
import { config } from "./helpers/types.js"
|
||||
|
||||
/**
|
||||
* Uploads an image to a fediverse instance
|
||||
* @param image The image to upload
|
||||
* @param sensitivity The sensitivity of the image
|
||||
* @param cfg {@link config} object
|
||||
* @returns { Promise<void> } Nothing
|
||||
*/
|
||||
export default async function postImage(
|
||||
image: ReadStream | Readable,
|
||||
sensitivity: boolean,
|
||||
cfg: config
|
||||
): Promise<void> {
|
||||
// Make a client to upload
|
||||
const client = generator(
|
||||
cfg.type,
|
||||
cfg.instance,
|
||||
cfg.accessToken,
|
||||
cfg.refreshToken
|
||||
)
|
||||
|
||||
// Upload the image
|
||||
const upload = async () => client.uploadMedia(image)
|
||||
const res = await pRetry(upload, {
|
||||
retries: cfg.retries,
|
||||
onFailedAttempt: logRetry,
|
||||
}).catch((err) => {
|
||||
crashHandler("Error uploading image.", err, err.response.data)
|
||||
return {} as Response<Entity.Attachment>
|
||||
})
|
||||
|
||||
// Make the post
|
||||
const post = async () =>
|
||||
client.postStatus(args.message || cfg.message, {
|
||||
media_ids: [res.data.id],
|
||||
// Change this to make the post visibility you wish
|
||||
visibility: cfg.visibility,
|
||||
sensitive: sensitivity,
|
||||
})
|
||||
await pRetry(post, {
|
||||
retries: cfg.retries,
|
||||
onFailedAttempt: logRetry,
|
||||
}).catch((err) => {
|
||||
crashHandler("Error uploading image", err, err.response.data)
|
||||
})
|
||||
|
||||
console.log(`Successfully posted to ${cfg.instance}`)
|
||||
}
|
||||
|
||||
function logRetry(error: unknown) {
|
||||
console.error("Retrying, error:")
|
||||
console.error(error)
|
||||
}
|
|
@ -1,37 +1,61 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
/* Basic Options */
|
||||
"target": "ESNext" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */,
|
||||
"module": "ESNext" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
|
||||
"lib": [
|
||||
"es6"
|
||||
] /* Specify library files to be included in the compilation. */,
|
||||
"outDir": "./dist" /* Redirect output structure to the directory. */,
|
||||
"removeComments": true /* Do not emit comments to output. */,
|
||||
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */,
|
||||
"importHelpers": false /* Import emit helpers from 'tslib'. */,
|
||||
"downlevelIteration": true /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */,
|
||||
"target": "esnext", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
|
||||
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
|
||||
"lib": ["es6"], /* Specify library files to be included in the compilation. */
|
||||
// "allowJs": true, /* Allow javascript files to be compiled. */
|
||||
// "checkJs": true, /* Report errors in .js files. */
|
||||
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
|
||||
// "declaration": true, /* Generates corresponding '.d.ts' file. */
|
||||
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
||||
// "sourceMap": true, /*es Generates corresponding '.map' file. */
|
||||
// "outFile": "./", /* Concatenate and emit output to single file. */
|
||||
"outDir": "./dist", /* Redirect output structure to the directory. */
|
||||
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
||||
// "composite": true, /* Enable project compilation */
|
||||
"removeComments": true, /* Do not emit comments to output. */
|
||||
"forceConsistentCasingInFileNames": true, /* Disallow inconsistently-cased references to the same file. */
|
||||
// "noEmit": true, /* Do not emit outputs. */
|
||||
"importHelpers": true, /* Import emit helpers from 'tslib'. */
|
||||
"downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
||||
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
||||
|
||||
/* Strict Type-Checking Options */
|
||||
"strict": true /* Enable all strict type-checking options. */,
|
||||
"noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */,
|
||||
"strictNullChecks": true /* Enable strict null checks. */,
|
||||
"strictFunctionTypes": true /* Enable strict checking of function types. */,
|
||||
"strictPropertyInitialization": true /* Enable strict checking of property initialization in classes. */,
|
||||
"noImplicitThis": true /* Raise error on 'this' expressions with an implied 'any' type. */,
|
||||
"alwaysStrict": true /* Parse in strict mode and emit "use strict" for each source file. */,
|
||||
"strict": true, /* Enable all strict type-checking options. */
|
||||
"noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
|
||||
"strictNullChecks": true, /* Enable strict null checks. */
|
||||
"strictFunctionTypes": true, /* Enable strict checking of function types. */
|
||||
"strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
|
||||
"noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
|
||||
"alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
||||
|
||||
/* Additional Checks */
|
||||
"noUnusedLocals": true /* Report errors on unused locals. */,
|
||||
"noUnusedParameters": true /* Report errors on unused parameters. */,
|
||||
"noImplicitReturns": true /* Report error when not all code paths in function return a value. */,
|
||||
"noFallthroughCasesInSwitch": true /* Report errors for fallthrough cases in switch statement. */,
|
||||
"noUnusedLocals": true, /* Report errors on unused locals. */
|
||||
"noUnusedParameters": true, /* Report errors on unused parameters. */
|
||||
"noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
||||
"noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
||||
|
||||
/* Module Resolution Options */
|
||||
"moduleResolution": "NodeNext" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */,
|
||||
"allowSyntheticDefaultImports": true /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */,
|
||||
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
|
||||
"sourceMap": true /* Generates corresponding '.map' file. */
|
||||
"moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
||||
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
|
||||
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
||||
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
||||
// "typeRoots": [], /* List of folders to include type definitions from. */
|
||||
// "types": [], /* Type declaration files to be included in compilation. */
|
||||
"allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
||||
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
||||
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
||||
|
||||
/* Source Map Options */
|
||||
// "sourceRoot": "./", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
|
||||
// "mapRoot": "./", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
|
||||
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
|
||||
|
||||
/* Experimental Options */
|
||||
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
||||
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
||||
},
|
||||
"include": ["./src"]
|
||||
}
|
||||
|
|
Reference in a new issue