Compare commits

...

3 Commits

Author SHA1 Message Date
76185a2ba4 Updated to use 2d matrix for post setting 2022-10-11 23:11:48 -07:00
0e82467772 Updated to use 2d matrix for post setting 2022-10-11 23:09:02 -07:00
e84c82067d Added cron script 2022-10-11 23:08:38 -07:00
5 changed files with 90 additions and 17 deletions

1
.gitignore vendored
View File

@ -2,6 +2,7 @@
/rsc*/ /rsc*/
/md5/ /md5/
/src/cfg*.py /src/cfg*.py
/log.txt
# Virtual environment # Virtual environment
/venv* /venv*

46
cron.sh Executable file
View File

@ -0,0 +1,46 @@
#! /usr/bin/env bash
# Yandere Lewd Bot, an image posting bot for Pleroma
# Copyright (C) 2022 Anon <yanderefedi@proton.me>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# WARNING: This script has not been thoroughly tested. Use at your own risk.
# Get the runtime path of the bot
ABS_PATH="$(readlink -f "$0")"
RUN_DIR="$(dirname "$ABS_PATH")"
# Relative paths to the entry point and log file
# Make sure the relative path is the same as the absolute path in your cron file
LOG='./log.txt'
ENTRY='./run.sh'
# cd into the bot's root path, set up the virtual environment, and run
cd "$RUN_DIR"
[ ! -f "$ENTRY" ] && echo "Cannot find entry: ${ENTRY}" && cd - > /dev/null && exit 1
if [ ! -f "$LOG" ]; then
"$ENTRY"
else
INDEX="$(expr `grep "^Profile" "$LOG" | cut -d ' ' -f5 | tail -n 1` + 1)"
STATE="$(grep "^State" "$LOG" | cut -d ' ' -f2 | tail -n 1 | awk -F ',' "{sub(\$${INDEX},\$${INDEX}+1,\$${INDEX})}7" | tr ' ' ',')"
"$ENTRY" -i "$INDEX" -s "$STATE"
fi
RETURN_CODE="$?"
# Cleanup
cd - > /dev/null
exit "$RETURN_CODE"

View File

@ -98,6 +98,7 @@ settings_backend = {
"url": "https://danbooru.donmai.us" "url": "https://danbooru.donmai.us"
}, },
# The below backends are still being tested # The below backends are still being tested
# Use at your own risk
"konachan_backend": { "konachan_backend": {
"module": "konachan_backend", "module": "konachan_backend",
"username": None, "username": None,
@ -120,7 +121,8 @@ settings_backend = {
# Apply post settings # Apply post settings
# Post settings consist of a 2d matrix with both the x and y axis increased per post
settings_post = ( settings_post = (
setup_profile("danbooru.random", "danbooru_backend", banned_tags, ("random",), "#random", "#random #nsfw #lewd"), (setup_profile("danbooru.random", "danbooru_backend", banned_tags, ("random",), "#random", "#random #nsfw #lewd"),),
setup_profile("danbooru.yandere", "danbooru_backend", banned_tags, ("yandere",), "#yandere", "#yandere #nsfw #lewd"), (setup_profile("danbooru.yandere", "danbooru_backend", banned_tags, ("yandere",), "#yandere", "#yandere #nsfw #lewd"),)
) )

View File

@ -42,7 +42,8 @@ def main():
parser.add_argument("--debug", help="Same as --dry-run", action="store_true") parser.add_argument("--debug", help="Same as --dry-run", action="store_true")
parser.add_argument("-c", "--config", help="Set custom config file (Default: {})".format(default_cfg), default=default_cfg) parser.add_argument("-c", "--config", help="Set custom config file (Default: {})".format(default_cfg), default=default_cfg)
parser.add_argument("-k", "--keyfile", help="Keyfile used for decryption") parser.add_argument("-k", "--keyfile", help="Keyfile used for decryption")
parser.add_argument("-i", "--index", help="Start at index (only matters if profile is set to sequential", default=0) parser.add_argument("-i", "--index", help="Start at index (only matters if profile is set to sequential)", default=0)
parser.add_argument("-s", "--state", help="Set comma seperated state (only matters if profile is set to sequential)", default=None)
parser.add_argument("remainder", help=argparse.SUPPRESS, nargs=argparse.REMAINDER) parser.add_argument("remainder", help=argparse.SUPPRESS, nargs=argparse.REMAINDER)
arguments = parser.parse_args() arguments = parser.parse_args()
@ -67,6 +68,12 @@ def main():
) )
yandere.currentIndexCount = int(arguments.index) yandere.currentIndexCount = int(arguments.index)
if arguments.state:
state = arguments.state.split(",")
if len(state) != len(yandere_config.settings_post):
print("State length does not match profile length. Ignoring...")
else:
yandere.currentProfileIndex = list(map(int, state))
# Setup exit calls # Setup exit calls
# Must be done after we declare our bot(s), otherwise this will be called if quitting on decrypting settings ) # Must be done after we declare our bot(s), otherwise this will be called if quitting on decrypting settings )

View File

@ -24,6 +24,7 @@ import shutil
import importlib import importlib
import magic import magic
import random import random
import copy
from threading import Event from threading import Event
from mastodon import Mastodon, MastodonIllegalArgumentError, MastodonAPIError, MastodonVersionError from mastodon import Mastodon, MastodonIllegalArgumentError, MastodonAPIError, MastodonVersionError
@ -49,6 +50,7 @@ class YandereBot:
consecutive_failed_uploads = 0 consecutive_failed_uploads = 0
currentSessionCount = 0 currentSessionCount = 0
currentIndexCount = 0 currentIndexCount = 0
currentProfileIndex = tuple()
debug_mode = False debug_mode = False
primed = False primed = False
decrypted = False decrypted = False
@ -62,6 +64,7 @@ class YandereBot:
self.load_settings(self.cfg) self.load_settings(self.cfg)
self.debug_mode = debug_mode or self.settings_behavior["debug"] self.debug_mode = debug_mode or self.settings_behavior["debug"]
self.settings_encrypt["keyfile"] = keyfile or self.settings_encrypt["keyfile"] self.settings_encrypt["keyfile"] = keyfile or self.settings_encrypt["keyfile"]
self.currentProfileIndex = [0]*len(self.settings_post)
random.seed(os.urandom(16)) random.seed(os.urandom(16))
if prime_bot: if prime_bot:
self.prime_bot() self.prime_bot()
@ -125,11 +128,18 @@ class YandereBot:
url = picked["file_url"] if picked else None url = picked["file_url"] if picked else None
path = picked["full_path"] if picked else None path = picked["full_path"] if picked else None
nsfw = picked["nsfw"] if picked else None nsfw = picked["nsfw"] if picked else None
index = (self.currentIndexCount - int(self.currentSessionCount > 0)) % len(self.settings_post)
posted_once = int(self.currentSessionCount > 0)
index = (self.currentIndexCount - posted_once) % len(self.settings_post)
state_print = copy.copy(self.currentProfileIndex)
state_print[index] = state_print[index] - posted_once
state_print = [state_print[i] % len(self.settings_post[i]) for i in range(0, len(self.currentProfileIndex))]
print("Profile: {} | Index: {} | NSFW: {} | Path: {} | URL: {}".format( print("Profile: {} | Index: {} | NSFW: {} | Path: {} | URL: {}".format(
profile, index, nsfw, path, url profile, index, nsfw, path, url
)) ))
print("State: {}".format(','.join(map(str, state_print))))
# Returns a list of media paths (without the hashes) # Returns a list of media paths (without the hashes)
def download_media(self, picked_profile): def download_media(self, picked_profile):
@ -235,15 +245,22 @@ class YandereBot:
return picked return picked
def pick_index(self, mode, current_index, length):
if mode == "random":
return random.randint(0, length - 1)
elif mode == "sequential":
return current_index % length
def pick_profile(self): def pick_profile(self):
profiles = self.settings_post # Get x and y
tag_select = self.settings_behavior["tag_select"].lower() mode = self.settings_behavior["tag_select"].lower()
pick_index = None posts = self.settings_post
if tag_select == "random": x = self.pick_index(mode, self.currentIndexCount, len(posts))
pick_index = random.randint(0, len(profiles) - 1) y = self.pick_index(mode, self.currentProfileIndex[x], len(posts[x]))
elif tag_select == "sequential":
pick_index = self.currentIndexCount % len(profiles) # Return the Profile
return profiles[pick_index] return x, y
# The main post function # The main post function
@ -260,7 +277,8 @@ class YandereBot:
# Attempt post # Attempt post
try: try:
# Post # Post
picked_profile = self.pick_profile() x, y = self.pick_profile()
picked_profile = self.settings_post[x][y]
picked = self.download_media(picked_profile) picked = self.download_media(picked_profile)
self._post(picked) self._post(picked)
@ -269,6 +287,9 @@ class YandereBot:
# After a successful post # After a successful post
self.currentSessionCount += 1 self.currentSessionCount += 1
self.consecutive_failed_uploads = 0 self.consecutive_failed_uploads = 0
# Set indexes
self.currentProfileIndex[x] += 1
self.currentIndexCount += 1 self.currentIndexCount += 1
# The post was successful # The post was successful
@ -362,7 +383,3 @@ class FailedLogin(Exception):
class BadCfgFile(Exception): class BadCfgFile(Exception):
pass pass
class MissingMasterList(Exception):
pass