feat: added poll module

This commit is contained in:
Soumt Nam 2023-10-03 11:01:27 +09:00
parent 4d10a9bd20
commit 26604978bf
No known key found for this signature in database
GPG key ID: 5F46B099DCBCA8CE
13 changed files with 481 additions and 307 deletions

View file

@ -1,12 +1,14 @@
from module_interface import ModuleInterface
class MyModule(ModuleInterface):
def __init__(self):
super().__init__()
self.name = "DummyModule1"
self.regex_pattern = None #r"my_pattern"
self.regex_pattern = None # r"my_pattern"
#print("[Dummy1] DummyModule1 loaded.")
# print("[Dummy1] DummyModule1 loaded.")
def execute_module(self, ctx):
#print(f"[Dummy1] {self.name} 실행: {ctx}")
# print(f"[Dummy1] {self.name} 실행: {ctx}")
pass

View file

@ -1,5 +1,6 @@
from pyfiglet import Figlet
f = Figlet(font='small')
f = Figlet(font="small")
import os
import importlib.util
@ -15,6 +16,7 @@ from aiohttp import ClientWebSocketResponse
from mipac.models.notification import NotificationNote
from mipa.ext.commands.bot import Bot
def load_modules():
module_dir = "modules"
modules = []
@ -29,10 +31,15 @@ def load_modules():
for attribute_name in dir(module):
attribute = getattr(module, attribute_name)
if inspect.isclass(attribute) and issubclass(attribute, ModuleInterface) and attribute != ModuleInterface:
if (
inspect.isclass(attribute)
and issubclass(attribute, ModuleInterface)
and attribute != ModuleInterface
):
modules.append(attribute())
return modules
class MiNya(Bot):
def __init__(self):
super().__init__()
@ -40,7 +47,8 @@ class MiNya(Bot):
self.__manager = ModuleManager(self)
async def _connect_channel(self):
await self.router.connect_channel(['main'])
await self.router.connect_channel(["main"])
async def on_reconnect(self, ws: ClientWebSocketResponse):
await self._connect_channel()
@ -66,27 +74,30 @@ class MiNya(Bot):
async def on_mention(self, notice: NotificationNote):
print("[Main] Got Mentioned!")
for _, module in self.__manager.modules.items():
if module.regex_pattern and re.match(module.regex_pattern, notice.note.content):
if module.regex_pattern and re.match(
module.regex_pattern, notice.note.content
):
print("[Main] Regex Matching Module found : ", module.name)
if await module.execute_module(notice.note):
break
def main():
print(f.renderText('MiNya V1'))
print(f.renderText("MiNya V1"))
print('"MIsskey Networked Yet Ambitious"')
print('')
print("")
print("[Main] Minya V1 Bootstap...")
print("[Main] Loading settings...")
load_dotenv()
instance = os.environ.get('BOT_INSTANCE')
key = os.environ.get('BOT_KEY')
instance = os.environ.get("BOT_INSTANCE")
key = os.environ.get("BOT_KEY")
if not (instance and key):
print("[MAIN] ERR! please check .env or os environment!")
return
bot = MiNya()
asyncio.run(bot.start(f'wss://{instance}/streaming', key))
asyncio.run(bot.start(f"wss://{instance}/streaming", key))
if __name__ == "__main__":
main()

View file

@ -1,5 +1,6 @@
from mipa.ext.commands.bot import Bot
class ModuleInterface:
def __init__(self):
self.name = None
@ -9,7 +10,7 @@ class ModuleInterface:
def set_manager(self, manager):
self.manager = manager
#self.module_ready()
# self.module_ready()
def get_execute_pattern(self, regex_pattern):
return self.__regex_pattern
@ -25,7 +26,7 @@ class ModuleInterface:
class ModuleManager:
def __init__(self, main_bot = None):
def __init__(self, main_bot=None):
self.modules = {}
self.bot: (Bot | None) = main_bot

View file

@ -2,230 +2,232 @@ from module_interface import ModuleInterface
import random
itemPrefixes = [
'플라티나로 만든',
'신선한',
'최신의',
'고대의',
'수제',
'시계장치의',
'전설의',
'구이',
'날것의',
'미냐가 만든',
'포켓 사이즈',
'사흘 전의',
'그 근처의',
'',
'사용된',
'고장난',
'시판되는',
'주문제작된',
'업무용의',
'Microsoft제',
'Apple제',
'인류 기술의 결정체인',
'2021년산',
'500kg정도의',
'고오급',
'썩은',
'인공지능 탑재',
'블록체인 탑재',
'반중력',
'접이식',
'휴대용',
'유전자 재조합',
'돌연변이로 비행 능력이 있는',
'순금으로 만든',
'투명한',
'빛나는',
'하트 모양의',
'움직이는',
'반으로 잘린',
'USB 커넥터가 달린',
'지난 날의',
'저주받은',
'인챈트된',
'하루치의 비타민이 들어간',
'손을 댄',
'환상의',
'가상의',
'원자력',
'고도로 훈련받은',
'유전자 조작이 아닌',
'런던 중심부에서 발견된',
'이세계의',
'다른 별의',
'수수께끼의',
'시공을 일그러뜨리는',
'이상한 소리가 나는',
'무산된',
'플라즈마화된',
'충격을 주면 낮은 확률로 폭발하는',
'주키니로 변신한',
'가설의',
'독이 있는',
'진짜',
'궁극의',
'초코가 들어간',
'악취가 나는',
'4차원',
'박동하는',
'정체를 알 수 없는',
'네모난',
'날뛰는',
'꿈의',
'어둠의',
'암흑의',
'봉인된',
'죽음의',
'얼어버린',
'마의',
'금단의',
'홀로그래픽',
'유압식',
"플라티나로 만든",
"신선한",
"최신의",
"고대의",
"수제",
"시계장치의",
"전설의",
"구이",
"날것의",
"미냐가 만든",
"포켓 사이즈",
"사흘 전의",
"그 근처의",
"",
"사용된",
"고장난",
"시판되는",
"주문제작된",
"업무용의",
"Microsoft제",
"Apple제",
"인류 기술의 결정체인",
"2021년산",
"500kg정도의",
"고오급",
"썩은",
"인공지능 탑재",
"블록체인 탑재",
"반중력",
"접이식",
"휴대용",
"유전자 재조합",
"돌연변이로 비행 능력이 있는",
"순금으로 만든",
"투명한",
"빛나는",
"하트 모양의",
"움직이는",
"반으로 잘린",
"USB 커넥터가 달린",
"지난 날의",
"저주받은",
"인챈트된",
"하루치의 비타민이 들어간",
"손을 댄",
"환상의",
"가상의",
"원자력",
"고도로 훈련받은",
"유전자 조작이 아닌",
"런던 중심부에서 발견된",
"이세계의",
"다른 별의",
"수수께끼의",
"시공을 일그러뜨리는",
"이상한 소리가 나는",
"무산된",
"플라즈마화된",
"충격을 주면 낮은 확률로 폭발하는",
"주키니로 변신한",
"가설의",
"독이 있는",
"진짜",
"궁극의",
"초코가 들어간",
"악취가 나는",
"4차원",
"박동하는",
"정체를 알 수 없는",
"네모난",
"날뛰는",
"꿈의",
"어둠의",
"암흑의",
"봉인된",
"죽음의",
"얼어버린",
"마의",
"금단의",
"홀로그래픽",
"유압식",
]
items = [
'가지',
'토마토',
'오이',
'감자',
'볶음국수',
'허리',
'초밥',
'호박',
'유키치',
'금괴',
'알루미늄',
'나트륨',
'마그네슘',
'플루토늄',
'작은 금속',
'우유팩',
'페트병',
'쿠키',
'초콜릿',
'메이드복',
'오렌지',
'니삭스',
'반물질 콘덴서',
'입자가속기',
'마이크로프로세서 (8코어 16스레드)',
'원자력 발전소',
'L4 스위치',
'완충 체인',
'양전자 두뇌',
'행성',
'테르민',
'충치차',
'마운터',
'버킷 휠 익스커베이터',
'데몬 코어',
'게임보이 어드밴스',
'양자컴퓨터',
'아나몰픽 렌즈',
'벽장에서 나온 수수께끼의 생물',
'스마트폰',
'시계',
'푸딩',
'가브리엘의 나팔',
'맹거의 스펀지',
'피젯 스피너',
'초입방체',
'건축물',
'에너지 드링크',
'마우스 커서',
'안경',
'참치',
'쓰레기통',
'이쑤시개',
'도시락에 들어가는 초록색 칸막이같은 녀석',
'나무젓가락',
'환기구',
'페트병의 뚜껑',
'소파 블럭',
'피자',
'치약',
'깡통',
'열쇠고리',
'금발 벽안의 미소녀',
'SD카드',
'립 크림',
'초코 없는 초코소라빵',
'조류독감',
'자판기',
'무거운 것',
'노트북',
'육포',
'연어 치즈',
'다이아몬드',
'물체',
'월석',
'특이점',
'중성자별',
'액체',
'위성',
'주키니',
'검은 것',
'흰 것',
'빨간 것',
'동그란 것',
'네모난 것',
'카드 모양의 것',
'기체',
'연필',
'지우개',
'양날검',
'막대 모양의 것',
'농산물',
'메탈 슬라임',
'문어발',
'버섯',
'나메코',
'호로요이',
'손톱깎기',
'귓속말',
'인형',
'티라노사우르스',
'요로결석',
'엔터 키',
'항아리',
'수은',
'',
'토지',
'대륙',
'주사위',
'실외기',
'유압잭',
'타피오카',
'PSP',
'화장지 심지',
'골판지 상자',
'하니와',
'볼펜',
'샤펜',
'원자',
'우주',
'소립자',
'참기름',
'undefined',
'None',
'NAN',
'[object Object]'
"가지",
"토마토",
"오이",
"감자",
"볶음국수",
"허리",
"초밥",
"호박",
"유키치",
"금괴",
"알루미늄",
"나트륨",
"마그네슘",
"플루토늄",
"작은 금속",
"우유팩",
"페트병",
"쿠키",
"초콜릿",
"메이드복",
"오렌지",
"니삭스",
"반물질 콘덴서",
"입자가속기",
"마이크로프로세서 (8코어 16스레드)",
"원자력 발전소",
"L4 스위치",
"완충 체인",
"양전자 두뇌",
"행성",
"테르민",
"충치차",
"마운터",
"버킷 휠 익스커베이터",
"데몬 코어",
"게임보이 어드밴스",
"양자컴퓨터",
"아나몰픽 렌즈",
"벽장에서 나온 수수께끼의 생물",
"스마트폰",
"시계",
"푸딩",
"가브리엘의 나팔",
"맹거의 스펀지",
"피젯 스피너",
"초입방체",
"건축물",
"에너지 드링크",
"마우스 커서",
"안경",
"참치",
"쓰레기통",
"이쑤시개",
"도시락에 들어가는 초록색 칸막이같은 녀석",
"나무젓가락",
"환기구",
"페트병의 뚜껑",
"소파 블럭",
"피자",
"치약",
"깡통",
"열쇠고리",
"금발 벽안의 미소녀",
"SD카드",
"립 크림",
"초코 없는 초코소라빵",
"조류독감",
"자판기",
"무거운 것",
"노트북",
"육포",
"연어 치즈",
"다이아몬드",
"물체",
"월석",
"특이점",
"중성자별",
"액체",
"위성",
"주키니",
"검은 것",
"흰 것",
"빨간 것",
"동그란 것",
"네모난 것",
"카드 모양의 것",
"기체",
"연필",
"지우개",
"양날검",
"막대 모양의 것",
"농산물",
"메탈 슬라임",
"문어발",
"버섯",
"나메코",
"호로요이",
"손톱깎기",
"귓속말",
"인형",
"티라노사우르스",
"요로결석",
"엔터 키",
"항아리",
"수은",
"",
"토지",
"대륙",
"주사위",
"실외기",
"유압잭",
"타피오카",
"PSP",
"화장지 심지",
"골판지 상자",
"하니와",
"볼펜",
"샤펜",
"원자",
"우주",
"소립자",
"참기름",
"undefined",
"None",
"NAN",
"[object Object]",
]
ands = [
[None, None, '에 빙의한'],
[None, None, '에 들어가는'],
[None, None, '에 묻힌'],
['', '', ' 연상시키는'],
[None, None, ' 같은'],
['으로', '', ' 가장한'],
[None, None, '에 올려진'],
[None, None, ' 옆에 있는'],
];
[None, None, "에 빙의한"],
[None, None, "에 들어가는"],
[None, None, "에 묻힌"],
["", "", " 연상시키는"],
[None, None, " 같은"],
["으로", "", " 가장한"],
[None, None, "에 올려진"],
[None, None, " 옆에 있는"],
]
from mipac.models import Note
class AiTem(ModuleInterface):
def __init__(self):
super().__init__()
@ -242,9 +244,28 @@ class AiTem(ModuleInterface):
def _generate(self):
item1_sel = random.choice(items)
con_sel = random.choice(ands)
item1_comp = self.manager.require("K-Josa").get_func("process_josa")(item1_sel, con_sel[0], con_sel[1]) + con_sel[2]
item1_comp = (
self.manager.require("K-Josa").get_func("process_josa")(
item1_sel, con_sel[0], con_sel[1]
)
+ con_sel[2]
)
return random.choice(itemPrefixes) + ' ' + ((item1_comp + ' ' + random.choice(itemPrefixes) + ' ' + random.choice(items)) if random.choice([True, False]) else item1_sel)
return (
random.choice(itemPrefixes)
+ " "
+ (
(
item1_comp
+ " "
+ random.choice(itemPrefixes)
+ " "
+ random.choice(items)
)
if random.choice([True, False])
else item1_sel
)
)
def module_ready(self):
print("[Ai-tem] Module Ready.")

View file

@ -37,10 +37,9 @@ Amumals = {
"앗 또 까먹었어..!",
"기게-엑",
"(사악한 웃음)",
"하와와..."
"하와와...",
]
}
}
class Amumal(ModuleInterface):
@ -61,6 +60,14 @@ class Amumal(ModuleInterface):
kjosa = self.manager.require("K-Josa").get_func("process_josa")
if random.choice([True, False]):
await self.manager.bot.client.note.action.send(random.choice(Amumals["notes"] + [kjosa(aitem, "", "") + " 가지고 싶어요...", "오늘 산책 중에 " + kjosa(aitem, "", "") + " 봤어요!"]), visibility="home")
await self.manager.bot.client.note.action.send(
random.choice(
Amumals["notes"]
+ [
kjosa(aitem, "", "") + " 가지고 싶어요...",
"오늘 산책 중에 " + kjosa(aitem, "", "") + " 봤어요!",
]
),
visibility="home",
)
print("[Amumal] Sent Amumal!")

107
modules/Amumal_poll.py Normal file
View file

@ -0,0 +1,107 @@
from asyncio import sleep
from mipa import Note
from module_interface import ModuleInterface
from mipa.ext import tasks
from mipac import ICreatePoll, MiPoll
import random
polls = [
['신기해 보이는 것들', '여러분, 어떤 게 가장 신기할 것 같나요?'],
['맛있을 것 같은 거', '여러분은 어떤 게 가장 맛있을 것 같아요?'],
['무거울 것 같은 것', '이 중에서 어느 게 가장 무거울 것 같나요?'],
['갖고 싶은 거', '여러분, 이 중에서 어느 게 가장 갖고 싶으세요?'],
['무인도에 가져가고 싶은 것', '여러분은 무인도에 한 가지를 가져갈 수 있다면 어떤 걸 가져가고 싶으세요?'],
['집에 장식하고 싶은 것', '여러분은 집에 어떤 장식을 다시나요?'],
['사업 아이템', '여러분은 어떤 게 가장 잘 팔릴 것 같아요?'],
['내렸으면 하는 것들', '여러분, 다음 중에서 어떤 게 하늘에서 내렸으면 좋겠어요?'],
['폰으로 하고 싶은 것', '여러분은 어떤 걸 핸드폰으로 갖고 싶어요?'],
['상품화하고 싶은 것', '여러분들은 상품화 하면 어떤 거 할래요?'],
['발굴될 만한 것', '여러분은 유적에서 발굴될 것 같은 것은 무엇이라고 생각하시나요?'],
['향기가 좋을 것 같은 것', '여러분들은 어떤 게 가장 좋은 향기가 난다고 생각하시나요?'],
['뭔가 비쌀 것 같은 것', '여러분은 어떤 게 가장 고가에 거래될 꺼라고 생각하시나요?'],
['지구 궤도상에 있을 법한 것', '여러분은 어떤 게 지구 궤도를 떠다닐 것 같다고 생각하세요?'],
['선물하고 싶은 것', '여러분은 저에게 어떤 선물을 주고 싶으신가요?'],
['선물 받고 싶은 것', '여러분은 어떤 걸 선물로 받고 싶으세요?'],
['제가 갖고 있을 것 같은 것', '여러분은 제가 어떤 걸 갖고 있을 것 같나요?'],
['유행할 법한 것', '여러분, 어떤 게 유행할 것 같아요?'],
['아침밥', '여러분은 아침밥으로 어떤 걸 드시고 싶으신가요?'],
['점심밥', '여러분, 점심은 뭐로 드시고 싶으세요?'],
['저녁밥', '여러분은 저녁에 어떤 걸 먹고 싶어요?'],
['몸에 좋은 것', '여러분은 어떤 게 몸에 좋을 것 같아요?'],
['후세에 물려주고 싶은 것', '여러분은 어떤 걸 후세에 물려주고 싶으세요?'],
['악기가 될 만한 것', '이 중에서 어떤 걸 악기로 쓸 수 있을까요?'],
['부대찌게에 넣을 만한 것', '여러분, 이 중에서 부대찌게에 넣을 만한 건 어떤 게 있을까요?'],
['후리카케 대용으로 쓰고 싶은 것', '여러분은 어떤 걸 밥에 뿌리고 싶으세요?'],
['자주 보는 것', '여러분, 어떤 걸 자주 보시나요'],
['길가에 떨어져 있을 만한 것', '길가에서 주울 수 있는 건 어떤 게 있을까요?'],
['미술관에 있을법한 것', '여러분은 이 중에서 어떤 게 미술관에 있을 것 같아요?'],
['교실에 있을 것 같은 것', '여러분은 어떤 게 교실에 있을 법한 것 같나요?'],
['이모지가 되었으면 하는 것', '이모지가 되었으면 하는 걸 골라주세요!'],
['CherryPick 본부에 있을 법한 것', '여러분, CherryPick 본부에는 어떤 게 있을 것 같나요?'],
['타는 쓰레기', '이 중에서 어느 게 타는 쓰레기일까요?'],
['좋아하는 삼각김밥 맛', '여러분이 좋아하는 삼각김밥 맛은 무엇인가요?']
]
class Amumal(ModuleInterface):
def __init__(self):
super().__init__()
self.name = "Amumal_Poll"
self.regex_pattern = None
print("[Amumal_Poll] Random Poll module, Amumal_Poll V1 loaded.")
def module_ready(self):
print("[Amumal_Poll] Module Ready.")
self.amumal_task.start()
@tasks.loop(seconds=(60.0 * 60))
async def amumal_task(self):
gen_aitem = self.manager.require("Ai-tem").get_func("generate")
if random.choice([True, False, False, False, False]):
generated_title = random.choice(polls)
gen_poll = MiPoll(
ICreatePoll(
expired_after=1000 * 60 * 60,
choices=[gen_aitem(), gen_aitem(), gen_aitem(), gen_aitem()],
)
)
sent_note = await self.manager.bot.client.note.action.send(
content=generated_title[1], visibility="home", poll=gen_poll
)
print("[Amumal_Poll] Poll started")
await sleep(60 * 60)
await self._poll_end(generated_title[0], sent_note)
async def _poll_end(self, title, p_note: Note):
p_choices = (await self.manager.bot.client.note.action.get(p_note.id)).poll.choices
kjosa = self.manager.require("K-Josa").get_func("process_josa")
mostVotedChoice = None
for p_choice in p_choices:
if mostVotedChoice == None:
mostVotedChoice = p_choice
continue
if p_choice.votes > mostVotedChoice.votes:
mostVotedChoice = p_choice
mostVotedChoices = list(filter(lambda x: x.votes == mostVotedChoice.votes, p_choices))
if mostVotedChoice.votes == 0:
await self.manager.bot.client.note.action.send(
content="아무도 투표하지 않았어요... :meow_melt_cry:",
visibility="home",
renote_id=p_note.id,
)
elif len(mostVotedChoices) == 1:
p_content = mostVotedChoice.text
else:
p_content = " 그리고 ".join((i.text for i in mostVotedChoices))
p_content = kjosa(p_content, "이었", "")
await self.manager.bot.client.note.action.send(
cw=f"{title} 설문조사 결과 발표에요!",
content=f"결과는 {mostVotedChoice.votes}표의 {p_content}어요.",
renote_id=p_note.id,
)
print("[Amumal_Poll] Poll ended :" + ", ".join((f"{i.text}:{i.votes}" for i in mostVotedChoices)))

View file

@ -2,6 +2,7 @@ from module_interface import ModuleInterface
from mipa.ext import tasks
import random
class Birthday(ModuleInterface):
def __init__(self):
super().__init__()
@ -16,5 +17,5 @@ class Birthday(ModuleInterface):
@tasks.loop(seconds=600.0)
async def birthday_task(self):
#awa
# awa
pass

View file

@ -1,6 +1,7 @@
from module_interface import ModuleInterface
from mipac.models import Note
class Follow(ModuleInterface):
def __init__(self):
super().__init__()

View file

@ -1,6 +1,7 @@
from module_interface import ModuleInterface
from mipac.models import Note
class Friend(ModuleInterface):
def __init__(self):
super().__init__()
@ -15,7 +16,9 @@ class Friend(ModuleInterface):
print("[Friend] Friend DB system, Friend V1 loaded.")
async def execute_module(self, ctx: Note):
await ctx.api.action.reply("1" if await self._is_friend_async(ctx.author.id) else "0")
await ctx.api.action.reply(
"1" if await self._is_friend_async(ctx.author.id) else "0"
)
def _dec_like(self, userid: str):
pass
@ -24,14 +27,16 @@ class Friend(ModuleInterface):
pass
def _get_like(self, userid: str):
return self._get_db(self.Name, userid)
return self._get_db(self.name, userid)["like"]
async def _is_friend_async(self, userid: str):
target = await self.manager.bot.user.api.action.get(userid)
return target.is_followed and target.is_following
def module_ready(self):
if self.manager != None:
self._get_db = self.manager.require("MinyaDB").get_func("get_module_db")
self._set_db = self.manager.require("MinyaDB").get_func("set_module_db")
else:
raise (Exception("Couldn't find manager"))
print("[Friend] Module Ready.")

View file

@ -1,6 +1,8 @@
from module_interface import ModuleInterface
from mipac.models import Note
class KJosa(ModuleInterface):
def __init__(self):
super().__init__()
@ -14,7 +16,18 @@ class KJosa(ModuleInterface):
pass
def _process(self, w, t, f):
return (w + ((t if ((ord(w[-1])- 44032) % 28 != 0) else f ) if (44032 <= ord(w[-1]) <= 55203) else f"{t}({f})")) if (t and f) else w
return (
(
w
+ (
(t if ((ord(w[-1]) - 44032) % 28 != 0) else f)
if (44032 <= ord(w[-1]) <= 55203)
else f"{t}({f})"
)
)
if (t and f)
else w
)
def module_ready(self):
print("[K-josa] Module Ready.")

View file

@ -2,6 +2,7 @@ from module_interface import ModuleInterface
from mipac.models import Note
import random
class MConch(ModuleInterface):
def __init__(self):
super().__init__()

View file

@ -3,6 +3,8 @@ from pupdb.core import PupDB
import os
from mipac.models import Note
class MinyaDB(ModuleInterface):
def __init__(self):
super().__init__()

View file

@ -1,6 +1,8 @@
import re
import asyncio
from module_interface import ModuleInterface
class Timer(ModuleInterface):
def __init__(self):
super().__init__()
@ -13,15 +15,15 @@ class Timer(ModuleInterface):
print(f"[Timer] Got Timer Related Message : {ctx.content}")
text = ctx.content
seconds_query = re.search(r'([0-9]+)초', text)
minutes_query = re.search(r'([0-9]+)분', text)
hours_query = re.search(r'([0-9]+)(시간)', text)
seconds_query = re.search(r"([0-9]+)초", text)
minutes_query = re.search(r"([0-9]+)분", text)
hours_query = re.search(r"([0-9]+)(시간)", text)
seconds = int(seconds_query.group(1)) if seconds_query else 0
minutes = int(minutes_query.group(1)) if minutes_query else 0
hours = int(hours_query.group(1)) if hours_query else 0
if ((seconds + minutes + hours) == 0):
if (seconds + minutes + hours) == 0:
await ctx.api.action.reply("올바른 값이 아니에요...")
time = (seconds) + (60 * minutes) + (60 * 60 * hours)