Compare commits

...

19 Commits

Author SHA1 Message Date
Captain Arepa b577623c5e Adjust post frequency
11 months ago
Captain Arepa af52982b11 fix regex for exclude_links
12 months ago
Captain Arepa b5de354345 adjust deploy for custom bots
1 year ago
Captain Arepa fc1a389b12 control commit
1 year ago
Captain Arepa 6637f96a28 Stuff:
1 year ago
Captain Arepa 9be514de78 control commit
1 year ago
Captain Arepa 9527b95cd7 control commit
1 year ago
Captain Arepa 6c602d881f reply thing wachamacallit
1 year ago
Captain Arepa 43cc9b3167 control commit
1 year ago
Captain Arepa e456e70094 Stuff
1 year ago
Captain Arepa 4bda3ffbe1 Merge remote-tracking branch 'origin/cachapa' into cachapa
1 year ago
Captain Arepa d38bb1b4d9 cc
1 year ago
Captain Arepa ec059a2761 Misc adjustments
1 year ago
Captain Arepa 98f8a24f69 Add on_reply
1 year ago
Captain Arepa 62e76ce284 10 minutes
1 year ago
Captain Arepa 2c7967dab4 control commit
1 year ago
Captain Arepa ce17d5d55a Update deploy script
1 year ago
Captain Arepa dc598527c9 Misc:
1 year ago
Captain Arepa 7742aecd0b Adjust requirements.txt
1 year ago

7
.gitignore vendored

@ -1,8 +1,11 @@
roboduck.db
markov.json
test-rd.py
bot.cfg
*.cfg
__pycache__
mia-markov-chain
.venv
notes.txt
notes.txt
nohup.
venv/
./venv/*

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (MIsskey-ebooks-bot)" project-jdk-type="Python SDK" />
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11 (misskey-ebooks-bot)" project-jdk-type="Python SDK" />
</project>

@ -4,7 +4,7 @@
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/venv" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="jdk" jdkName="Python 3.11 (misskey-ebooks-bot)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
<component name="PyDocumentationSettings">

@ -0,0 +1,29 @@
#!/bin/sh
USER=$1 # your ssh user
HOST=$2 # your server host
DIR=$3 # the directory where the bot files will go name it as you wish
BOT=$4 # the bot name
echo "Target directory: ${DIR}"
sleep 1
rm -rf ./"${DIR}"
# Copy and move the files to a directory
echo "Copying files..."
mkdir "${DIR}"
#cp -r venv/ ./"${DIR}"
#cp markov.json roboduck.db roboduck.py update.py rdbot.py bot.cfg requirements.txt run.sh ./"${DIR}"
cp roboduck.py update.py rdbot.py requirements.txt run.sh bot-"${BOT}".cfg ./"${DIR}"
mv ./"${DIR}"/bot-"${BOT}".cfg ./"${DIR}"/bot.cfg
# Uncomment this to run tests
# rsync -avz --dry-run live/ ${USER}@${HOST}:~/${DIR}
# Comment this one when running tests - this will delete everything on the server that's not in the local public folder
rsync -avz "${DIR}"/ "${USER}"@"${HOST}":~/"${DIR}"
echo "Deleting directory: ${DIR}..."
rm -rf ./"${DIR}"
exit 0

@ -1,8 +1,11 @@
import asyncio
import threading
import re
from time import sleep
from mipa.ext import commands, tasks
from mipa.router import Router
from mipac import LiteUser, UserManager, UserDetailed, NotificationReaction
from mipac.models import Note
from mipac.util import check_multi_arg
@ -13,6 +16,9 @@ config = roboduck.configparser.ConfigParser()
config.read(roboduck.Path(__file__).parent.joinpath('bot.cfg'))
url = "https://" + config.get("misskey", "instance_write")
token = config.get("misskey", "token")
instance_val = config.get("misskey", "instance_write")
instance_admin = config.get("misskey", "instance_admin")
post_frequency = float(config.get("markov", "post_frequency"))
try:
contentwarning = config.get("misskey", "cw")
@ -30,12 +36,36 @@ class MyBot(commands.Bot):
def __init__(self):
super().__init__()
@tasks.loop(3600)
@staticmethod
async def get_bot_data(user_manager: UserManager):
bot_user = await user_manager.action.get_me()
bot_host = instance_val
bot_short = '@' + bot_user.username
bot_long = bot_short + '@' + bot_host
return bot_host, bot_short, bot_long
@tasks.loop(seconds=3600)
async def loop_1h(self):
text = roboduck.create_sentence()
await bot.client.note.action.send(content=text, visibility="public", cw=contentwarning)
@tasks.loop(43200)
@tasks.loop(seconds=3600)
async def loop_2h(self):
text = roboduck.create_sentence()
await bot.client.note.action.send(content=text, visibility="public", cw=contentwarning)
@tasks.loop(seconds=600)
async def loop_10m(self):
text = roboduck.create_sentence()
await bot.client.note.action.send(content=text, visibility="public", cw=contentwarning)
@tasks.loop(seconds=post_frequency)
async def loop_custom(self):
print("POSTED! " + roboduck.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
text = roboduck.create_sentence()
await bot.client.note.action.send(content=text, visibility="public", cw=contentwarning)
@tasks.loop(seconds=43200)
async def loop_12h(self):
thread_update = threading.Thread(target=roboduck.update())
thread_update.daemon = True
@ -43,22 +73,86 @@ class MyBot(commands.Bot):
async def on_ready(self, ws):
await Router(ws).connect_channel(["global", "main"]) # Connect to global and main channels
await self.client.note.action.send(content=roboduck.datetime.now().strftime('%Y-%m-%d %H:%M:%S') + " Roboduck Bot started!",
visibility="specified")
await self.client.note.action.send(
content=roboduck.datetime.now().strftime('%Y-%m-%d %H:%M:%S') + " Roboduck Bot started!",
visibility="specified")
self.loop_12h.start() # Launching renew posts every 12 hours
self.loop_1h.start() #
# self.loop_1h.start() #
self.loop_2h.start() #
# self.loop_10m.start()
self.loop_custom.start() # Custom duration bot
print(roboduck.datetime.now().strftime('%Y-%m-%d %H:%M:%S') + " Roboduck Bot started!")
async def on_mention(self, note: Note):
if not note.author.is_bot:
text = note.author.action.get_mention() + " "
text += roboduck.create_sentence()
# because this doesn't work for some reason*, I redid this shit
# Get note user properties
lite_user: LiteUser = note.__getattribute__("user")
# Get user manager (for stuff)
user_api: UserManager = lite_user.api
# Get the bot's handle...
bot_host, bot_short, bot_long = await self.get_bot_data(user_api)
# print("Bot\n Host: {0} - Short handle: {1} - Long handle: {2}".format(bot_host, bot_short, bot_long))
await note.reply(content=text, cw=contentwarning) # Reply to a note
# Get note author and host
author_id = lite_user.id
author_user = lite_user.username
author_host = lite_user.host if lite_user.host is not None else bot_host
# print("Author: {0} - Host: {1}".format(author_user, author_host))
reply_to = "@{0}".format(author_user) if author_host == bot_host else "@{0}@{1}".format(author_user,
author_host)
# Get user details (only to validate if it's a f***ing bot)
user_detail = await user_api.action.fetch(author_id, author_user, author_host)
# is the author a
is_bot = user_detail.is_bot
# Get original note content
og_note: Note = note.__getattribute__("note")
# print("Note content: {0} ".format(og_note.content))
# Regex to do some magic
user_regex = "(?>@(?>[\w\-])+)(?>@(?>[\w\-\.])+)?"
# Find all mentions in the note
mentions = re.findall(user_regex, og_note.content)
# All users mentioned in the note
# print("All mentions:")
# print(mentions)
# Filter out the original author and the bot from the mentions
filtered = list(filter(lambda user: user not in [author_user, bot_short, bot_long], mentions))
# print("Filtered mentions:")
# print(filtered)
# Validate if it's not a bot, and then reply
if not is_bot:
text = reply_to + " " + ' '.join(filtered) + " "
text += roboduck.create_sentence()
# print("Resulting note:\n {0}".format(text))
await og_note.api.action.reply(content=text, cw=contentwarning)
async def on_reconnect(self, ws):
await Router(ws).connect_channel(["global", "main"]) # Connect to global and main channels
async def on_reply(self, note: Note):
# Just... follow the thread, eh?
await self.on_mention(note)
async def on_user_follow(self, user: UserDetailed):
# I'll add stuff here
print("test")
async def on_reaction(self, notice: NotificationReaction):
# I'll also add stuff here... later.
print("OI!")
if __name__ == "__main__":
databasepath = roboduck.Path(__file__).parent.joinpath('roboduck.db')
@ -66,4 +160,9 @@ if __name__ == "__main__":
roboduck.init_bot()
bot = MyBot()
asyncio.run(bot.start(url, token))
try:
asyncio.run(bot.start(url, token))
except Exception as e:
print("Failed to run, retrying...")
sleep(10)
asyncio.run(bot.start(url, token))

@ -4,5 +4,5 @@ ujson
requests
msgpack
regex
git+https://github.com/yupix/mipa.git
git+https://github.com/yupix/mipac.git
git+https://git.cachapa.xyz/mirror_maker/mipa.git
git+https://git.cachapa.xyz/mirror_maker/mipac.git

@ -23,7 +23,7 @@ def check_str_to_bool(text) -> bool:
def get_endpoint(instance: str) -> str:
# Try Misskey
url = "https://" + instance + "/api/ping"
req = requests.post(url)
req = requests.post(url, json={})
if req.status_code == 200 and ("pong" in req.json()):
return "Misskey"
@ -174,7 +174,7 @@ def misskey_get_notes(**kwargs):
content = content.replace("@", "@" + chr(8203))
if exclude_links:
content = regex.sub(r"(http|https):\/\/([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-]))",
content = regex.sub(r"(http|https):\/\/([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-])",
"", content)
note_dict = {"id": element["id"], "text": content, "timestamp": last_timestamp, "user_id": userid}
@ -256,7 +256,7 @@ def mastodon_get_notes(**kwargs):
run = True
oldnote = ""
base_url = "https://" + instance + "/api/v1/accounts/" + userid + "/statuses?limit=20&exclude_replies="\
base_url = "https://" + instance + "/api/v1/accounts/" + userid + "/statuses?limit=20&exclude_replies=" \
+ str(not include_replies)
if init:
@ -284,7 +284,7 @@ def mastodon_get_notes(**kwargs):
oldnote = note_id
note_id = notes_list[len(notes_list)-1]["id"]
note_id = notes_list[len(notes_list) - 1]["id"]
if init:
url = base_url + "&max_id=" + note_id
@ -324,7 +324,7 @@ def mastodon_get_notes(**kwargs):
content = content.replace("@", "@" + chr(8203)) # Add no-length-space behind @
if exclude_links:
content = regex.sub(r"(http|https):\/\/([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-]))",
content = regex.sub(r"(http|https):\/\/([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-])",
"", content)
note_dict = {"id": element["id"], "text": content, "timestamp": last_timestamp, "user_id": userid}
@ -359,6 +359,7 @@ def pleroma_get_notes(**kwargs):
return return_list
def get_user_id(username: str, instance: str) -> str:
# Determine API endpoint
api = get_endpoint(instance)

@ -0,0 +1,21 @@
#! /usr/bin/env bash
ABS_PATH="$(readlink -f "$0")"
RUN_DIR="$(dirname "$ABS_PATH")"
# Relative paths to main script
ENTRY='rdbot.py'
# cd into the bot's root path and run
# shellcheck disable=SC2164
cd "$RUN_DIR"
python3.11 "$ENTRY"
RETURN_CODE="$?"
# Cleanup
# shellcheck disable=SC2164
# shellcheck disable=SC2103
cd - > /dev/null
exit "$RETURN_CODE"
Loading…
Cancel
Save