fediverse-admin-bot/bot.py

119 lines
4.1 KiB
Python
Raw Normal View History

2024-08-28 17:16:11 +01:00
import time
import os
import sys
import logging
import random
from configparser import ConfigParser
from pathlib import Path
2024-08-28 17:16:11 +01:00
from misskey import Misskey
from misskey.exceptions import MisskeyAPIException
BASE = Path.cwd()
if (BASE / "data").exists():
BASE = BASE / "data"
print("Data/ directory found. Using it as base.")
2024-08-28 17:16:11 +01:00
logging.basicConfig(
filename=BASE / "bot.log",
2024-08-28 17:16:11 +01:00
filemode="a",
level=getattr(logging, os.getenv("LOGLEVEL", "INFO")),
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
)
logger = logging.getLogger("fedibot")
config = ConfigParser()
config.read(str(BASE / "config.ini"))
2024-08-28 17:16:11 +01:00
server_domain = list(config.keys())[1]
api_key = config[server_domain]["api_key"]
sleep_time = int(config[server_domain].get("sleep_time", 60))
limit = int(config[server_domain].get("limit", 100))
bot = Misskey(server_domain, api_key)
with open(BASE / "copy.txt") as _fd:
2024-08-28 17:16:11 +01:00
copy = _fd.read()
def main():
print("Bot running.")
while True:
try:
with open(BASE / ".lastfetch", "r") as fd:
2024-08-28 17:16:11 +01:00
lastfetch = fd.read()
logger.debug(f"Last fetch: {lastfetch}")
except FileNotFoundError:
lastfetch = os.getenv("EPOCH_ID")
logger.warning(f"No epoch for last fetch found. Using $EPOCH_ID: {lastfetch}")
for i in range(5):
try:
notifications = bot.i_notifications(
limit=100,
mark_as_read=True,
include_types=["reply", "mention"],
since_id=lastfetch,
)
except MisskeyAPIException as e:
logger.error("Failed to fetch notifications: %r", e, exc_info=True)
retry = random.uniform(0, 2**i)
2024-08-28 17:16:11 +01:00
logger.warning("Retrying in %.2f seconds...", retry)
time.sleep(retry)
else:
break
else:
logger.critical("Failed to fetch notifications after 5 retries. Exiting...")
sys.exit(1)
logger.debug("Fetched another batch of notifications: %r", notifications)
for notification in notifications:
if notification["note"]["user"].get("isBot", False) is True:
logger.debug("Ignoring bot: %r", notification["note"]["user"]["id"])
# Ignore bots
continue
logger.info("Replying to post %r", notification["note"]["id"])
try:
bot.notes_create(
text=copy.format(notification, bot),
reply_id=notification["note"]["id"],
visibility="specified",
visible_user_ids=[notification["user"]["id"]],
)
logger.info("Successfully replied to post %r", notification["note"]["id"])
try:
logger.info(
"Reacting with the inbox emoji to post %r",
notification["note"]["id"],
)
bot.notes_reactions_create(note_id=notification["note"]["id"], reaction="📥")
logger.info(
"Successfully reacted with the inbox emoji to post %r",
notification["note"]["id"],
)
except MisskeyAPIException:
logger.error(
"Failed to react with the inbox emoji to post %r",
notification["note"]["id"],
exc_info=True,
)
2024-08-28 17:16:11 +01:00
# Save that we replied to this post
with open(BASE / ".lastfetch", "w") as fd:
fd.write(notification["id"])
except MisskeyAPIException as e:
logger.error(
"Failed to reply to post %r: %r",
notification["note"]["id"],
e,
exc_info=True,
)
2024-08-28 17:16:11 +01:00
try:
time.sleep(sleep_time)
except KeyboardInterrupt:
break
if __name__ == "__main__":
main()