1
0

refactor: use json for config

feat: options for rate, visibility, template
feat: more flexible get line
This commit is contained in:
オスカー、 2023-11-24 14:13:21 +09:00
parent 08e32943c9
commit b9ffca44c2
No known key found for this signature in database
GPG Key ID: B1EFBBF5C93FF78F
5 changed files with 71 additions and 28 deletions

View File

@ -1,4 +0,0 @@
MISSKEY_TOKEN = YOUR_ACCESS_TOKEN_HERE
MISSKEY_ORIGIN = YOUR_MISSKEY_SERVER_HERE
MAX_DUPLICATE_COUNT = 3
SPREADSHEET_URL = YOUR_WORKSHEET_URL_HERE

1
.gitignore vendored
View File

@ -26,6 +26,7 @@ share/python-wheels/
*.egg *.egg
MANIFEST MANIFEST
.DS_Store .DS_Store
config.json
# PyInstaller # PyInstaller
# Usually these files are written by a python script from a template # Usually these files are written by a python script from a template

12
config.example.json Normal file
View File

@ -0,0 +1,12 @@
{
"token": "YOUR_ACCESS_TOKEN_HERE",
"origin": "YOUR_MISSKEY_SERVER_HERE",
"max_duplicate": 3,
"rate": 60,
"visibility": "home",
"worksheet": "YOUR_WORKSHEET_URL_HERE",
"template": {
"auto": "{note}",
"mention": "{note}\n \nFrom {from} ({number})"
}
}

View File

@ -7,9 +7,11 @@ from mipa.ext.commands.bot import Bot
class Post(commands.Cog): class Post(commands.Cog):
def __init__(self, bot: Bot) -> None: def __init__(self, bot: Bot) -> None:
self.bot = bot self.bot = bot
self.max_count = bot.config.max or 3
self.visibility = bot.config.visibility or "home"
self.posted = [] self.posted = []
@tasks.loop(seconds=60) @tasks.loop(seconds=1800)
async def _postLine(self) -> None: async def _postLine(self) -> None:
now = datetime.now() now = datetime.now()
if now.minute not in [30, 00]: # Only post in n:30 and n:00 if now.minute not in [30, 00]: # Only post in n:30 and n:00
@ -17,14 +19,18 @@ class Post(commands.Cog):
line = self.bot.get_random_line() line = self.bot.get_random_line()
while line in self.posted: while line in self.posted:
line = self.bot.get_line() line = self.bot.get_random_line()
await self.bot.client.note.action.send(content=line, visibility="home") template = self.bot.config.reply
result = template.replace("{text}", line.text).replace("{from}", line.where).replace("{number}", line.number)
await self.bot.client.note.action.send(content=result, visibility=self.visibility)
self.posted.append(line) self.posted.append(line)
if len(self.posted) > self.bot.max_count: if len(self.posted) > self.max_count:
self.posted.pop(0) self.posted.pop(0)
async def setup(bot: Bot): async def setup(bot: Bot):
cog = Post(bot) cog = Post(bot)
if bot.config.rate is not None:
cog._postLine.seconds = bot.config.rate * 60
await cog._postLine.start() await cog._postLine.start()
await bot.add_cog(cog) await bot.add_cog(cog)

68
main.py
View File

@ -1,4 +1,5 @@
import asyncio import asyncio
import json
import os import os
import random import random
@ -7,19 +8,50 @@ from aiohttp import ClientWebSocketResponse
from gspread.worksheet import Worksheet from gspread.worksheet import Worksheet
from mipac.models.notification import NotificationNote from mipac.models.notification import NotificationNote
from mipa.ext import commands from mipa.ext import commands
from dotenv import load_dotenv
load_dotenv()
class Config:
def __init__(self, path: str) -> None:
raw = json.load(path)
self.token = raw.get("token")
self.origin = raw.get("origin")
self.max = raw.get("max_duplicate")
self.rate = raw.get("rate")
self.visibility = raw.get("visibility")
self.worksheet = raw.get("worksheet")
template = raw.get("template")
self.note = template.get("auto")
self.reply = template.get("mention")
if any([
self.token is None,
self.origin is None,
self.worksheet is None,
self.note is None,
self.reply is None
]):
raise ValueError("config.json 파일에 일부 필수 값이 누락되었습니다.")
class Line:
def __init__(self, row: int, bot: "Autoposter") -> None:
sheet = bot.get_worksheet()
self.location = row
res = sheet.get(f"D{row}")
self.text = res[0][0].strip()
res = sheet.get(f"C{row}")
self.where = res[0][0].strip()
res = sheet.get(f"B{row}")
self.number = res[0][0].strip()
class Autoposter(commands.Bot): class Autoposter(commands.Bot):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.max_count = int(os.getenv("MAX_DUPLICATE_COUNT")) self.config: Config = Config("./config.json")
def get_worksheet(self) -> Worksheet: def get_worksheet(self) -> Worksheet:
gc = gspread.service_account() gc = gspread.service_account()
sh = gc.open_by_url(os.getenv("SPREADSHEET_URL")) sh = gc.open_by_url(self.config["worksheet"])
worksheet = sh.get_worksheet(0) worksheet = sh.get_worksheet(0)
return worksheet return worksheet
@ -31,17 +63,10 @@ class Autoposter(commands.Bot):
count = int(response[0][0]) count = int(response[0][0])
result = random.randint(1, count) result = random.randint(1, count)
number = result + 2 number = result + 2
res = sheet.get(f"D{number}") return Line(number, self)
text = res[0][0].strip()
return text
def get_info(self, line: str) -> dict: def get_line(self, number: int) -> str:
sheet = self.get_worksheet() return Line(number, self)
result = sheet.find(line, in_column=4)
number = result.row - 2
where = sheet.get(f"C{result.row}")
where = where[0][0]
return {"number": number, "from": where}
async def _connect_channel(self): async def _connect_channel(self):
await self.router.connect_channel(['main', 'global']) await self.router.connect_channel(['main', 'global'])
@ -56,17 +81,20 @@ class Autoposter(commands.Bot):
await self.load_extension(extension) await self.load_extension(extension)
async def on_reconnect(self, ws: ClientWebSocketResponse): async def on_reconnect(self, ws: ClientWebSocketResponse):
print("Disconnected from server.") print("Disconnected from server. Reconnecting...")
await self._connect_channel() await self._connect_channel()
async def on_mention(self, notice: NotificationNote): async def on_mention(self, notice: NotificationNote):
line = self.get_random_line() if notice.note.reply_id is not None:
info = self.get_info(line) return
await notice.note.api.action.reply(content=f"{line}\n \n<small>- {info['from']}에서 발췌됨. ({info['number']}번 대사)</small>", reply_id=notice.note.id)
line: Line = self.get_random_line()
template = self.config.reply
result = template.replace("{text}", line.text).replace("{from}", line.where).replace("{number}", line.number)
await notice.note.api.action.reply(content=result, visibility=notice.note.visibility, reply_id=notice.note.id)
if __name__ == '__main__': if __name__ == '__main__':
bot = Autoposter() bot = Autoposter()
loop = asyncio.get_event_loop() loop = asyncio.get_event_loop()
origin = os.getenv("MISSKEY_ORIGIN") loop.run_until_complete(bot.start(f"wss://{bot.config.origin}/streaming", os.getenv("MISSKEY_TOKEN")))
loop.run_until_complete(bot.start(f"wss://{origin}/streaming", os.getenv("MISSKEY_TOKEN")))