forked from mttu-developers/konabot
Merge branch 'master' of https://gitea.service.jazzwhom.top/mttu-developers/konabot
This commit is contained in:
1
assets/json/poll.json
Normal file
1
assets/json/poll.json
Normal file
@ -0,0 +1 @@
|
||||
{"poll": {"0": {"create": 1760357553, "expiry": 1760443953, "options": {"0": "此方bot", "1": "testpilot", "2": "小镜bot", "3": "可怜bot"}, "polldata": {}, "qq": "2975499623", "title": "我~是~谁~?"}}}
|
||||
11
konabot/docs/user/发起投票.txt
Normal file
11
konabot/docs/user/发起投票.txt
Normal file
@ -0,0 +1,11 @@
|
||||
指令介绍
|
||||
发起投票 - 发起一个投票
|
||||
|
||||
格式
|
||||
发起投票 <投票标题> <选项1> <选项2> ...
|
||||
|
||||
示例
|
||||
`发起投票 这是一个投票 A B C` 发起标题为“这是一个投票”,选项为“A”、“B”、“C”的投票
|
||||
|
||||
说明
|
||||
投票各个选项之间用空格分隔,选项数量为2-15项。投票的默认有效期为24小时。
|
||||
12
konabot/docs/user/投票.txt
Normal file
12
konabot/docs/user/投票.txt
Normal file
@ -0,0 +1,12 @@
|
||||
指令介绍
|
||||
投票 - 参与已发起的投票
|
||||
|
||||
格式
|
||||
投票 <投票ID/标题> <选项文本>
|
||||
|
||||
示例
|
||||
`投票 1 A` 在ID为1的投票中,投给“A”
|
||||
`投票 这是一个投票 B` 在标题为“这是一个投票”的投票中,投给“B”
|
||||
|
||||
说明
|
||||
目前不支持单人多投,每个人只能投一项。
|
||||
12
konabot/docs/user/查看投票.txt
Normal file
12
konabot/docs/user/查看投票.txt
Normal file
@ -0,0 +1,12 @@
|
||||
指令介绍
|
||||
查看投票 - 查看已发起的投票
|
||||
|
||||
格式
|
||||
查看投票 <投票ID或标题>
|
||||
|
||||
示例
|
||||
`查看投票 1` 查看ID为1的投票
|
||||
`查看投票 这是一个投票` 查看标题为“这是一个投票”的投票
|
||||
|
||||
说明
|
||||
投票在进行时,使用此命令可以看到投票的各个选项;投票结束后,则可以看到各项的票数。
|
||||
8
konabot/docs/user/生成二维码.txt
Normal file
8
konabot/docs/user/生成二维码.txt
Normal file
@ -0,0 +1,8 @@
|
||||
指令介绍
|
||||
生成二维码 - 将文本内容转换为二维码
|
||||
|
||||
格式
|
||||
生成二维码 <文本内容>
|
||||
|
||||
示例
|
||||
`生成二维码 嗨嗨嗨` 生成扫描结果为“嗨嗨嗨”的二维码图片
|
||||
69
konabot/plugins/gen_qrcode/__init__.py
Normal file
69
konabot/plugins/gen_qrcode/__init__.py
Normal file
@ -0,0 +1,69 @@
|
||||
import qrcode
|
||||
# from pyzbar.pyzbar import decode
|
||||
# from PIL import Image
|
||||
import requests
|
||||
from io import BytesIO
|
||||
|
||||
from nonebot_plugin_alconna import (Alconna, Args, Field, MultiVar, UniMessage,
|
||||
on_alconna)
|
||||
from nonebot_plugin_alconna.uniseg import UniMsg, At, Reply
|
||||
|
||||
async def download_img(url):
|
||||
resp = requests.get(url.replace("https://multimedia.nt.qq","http://multimedia.nt.qq")) # bim获取QQ的图片时避免SSLv3报错
|
||||
img_bytes = BytesIO()
|
||||
with open(img_bytes,"wb") as f:
|
||||
f.write(resp.content)
|
||||
return img_bytes
|
||||
|
||||
def genqr(data):
|
||||
qr = qrcode.QRCode(version=1,error_correction=qrcode.constants.ERROR_CORRECT_L,box_size=8,border=4)
|
||||
qr.add_data(data)
|
||||
qr.make(fit=True)
|
||||
img = qr.make_image(fill_color="black", back_color="white")
|
||||
img_bytes = BytesIO()
|
||||
img.save(img_bytes, format="PNG")
|
||||
return img_bytes
|
||||
|
||||
"""
|
||||
async def recqr(url):
|
||||
im_path = "assets/img/qrcode/2.jpg"
|
||||
data = await download_img(url)
|
||||
img = Image.open(im_path)
|
||||
decoded_objects = decode(img)
|
||||
data = ""
|
||||
for obj in decoded_objects:
|
||||
data += obj.data.decode('utf-8')
|
||||
return data
|
||||
"""
|
||||
|
||||
gqrc = on_alconna(Alconna(
|
||||
"genqr",
|
||||
Args["saying", MultiVar(str, '+'), Field(
|
||||
missing_tips=lambda: "请输入你要转换为二维码的文字!"
|
||||
)],
|
||||
# UniMessage[]
|
||||
), use_cmd_start=True, use_cmd_sep=False, skip_for_unmatch=False, aliases={"生成二维码","genqrcode"})
|
||||
|
||||
@gqrc.handle()
|
||||
async def _(saying: list):
|
||||
"""
|
||||
img = await draw_pt("\n".join(saying))
|
||||
img_bytes = BytesIO()
|
||||
img.save(img_bytes, format="PNG")
|
||||
|
||||
await pt.send(await UniMessage().image(raw=img_bytes).export())
|
||||
|
||||
# print(saying)
|
||||
# 二维码识别
|
||||
if type(saying[0]) == 'image':
|
||||
data = await recqr(saying[0].data['url'])
|
||||
if data == "":
|
||||
await gqrc.send("二维码图片解析失败!")
|
||||
else:
|
||||
await gqrc.send(recqr(saying[0].data['url']))
|
||||
|
||||
# 二维码生成
|
||||
else:
|
||||
"""
|
||||
# genqr("\n".join(saying))
|
||||
await gqrc.send(await UniMessage().image(raw=genqr("\n".join(saying))).export())
|
||||
160
konabot/plugins/poll/__init__.py
Normal file
160
konabot/plugins/poll/__init__.py
Normal file
@ -0,0 +1,160 @@
|
||||
import json, time
|
||||
|
||||
from nonebot_plugin_alconna import (Alconna, Args, Field, MultiVar, UniMessage,
|
||||
on_alconna)
|
||||
from nonebot_plugin_alconna.uniseg import UniMsg, At, Reply
|
||||
from nonebot.adapters.onebot.v11 import Event
|
||||
|
||||
poll_json_path = "assets/json/poll.json"
|
||||
|
||||
poll_file = open(poll_json_path,"r",encoding="utf-8")
|
||||
poll_list_raw = poll_file.read()
|
||||
poll_file.close()
|
||||
poll_list = json.loads(poll_list_raw)['poll']
|
||||
|
||||
async def createpoll(title,qqid,options):
|
||||
polllength = len(poll_list)
|
||||
pollid = str(polllength)
|
||||
poll_create = int(time.time())
|
||||
poll_expiry = poll_create + 24*3600
|
||||
polljson = {"title":title,"qq":qqid,"create":poll_create,"expiry":poll_expiry,"options":options,"polldata":{}}
|
||||
poll_list[pollid] = polljson
|
||||
writeback()
|
||||
return pollid
|
||||
|
||||
def getpolldata(pollid_or_title):
|
||||
# 初始化“被指定的投票项目”
|
||||
thepoll = {}
|
||||
polnum = -1
|
||||
# 判断是ID还是标题
|
||||
if str.isdigit(pollid_or_title):
|
||||
if pollid_or_title in poll_list:
|
||||
thepoll = poll_list[pollid_or_title]
|
||||
polnum = pollid_or_title
|
||||
else:
|
||||
return [{},-1]
|
||||
else:
|
||||
for i in poll_list:
|
||||
if poll_list[i]["title"] == pollid_or_title:
|
||||
thepoll = poll_list[i]
|
||||
polnum = i
|
||||
break
|
||||
if polnum == -1:
|
||||
return [{},-1]
|
||||
return [thepoll,polnum]
|
||||
|
||||
def writeback():
|
||||
file = open(poll_json_path,"w",encoding="utf-8")
|
||||
json.dump({'poll':poll_list},file,ensure_ascii=False,sort_keys=True)
|
||||
|
||||
async def pollvote(polnum,optionnum,qqnum):
|
||||
optiond = poll_list[polnum]["polldata"]
|
||||
if optionnum not in optiond:
|
||||
poll_list[polnum]["polldata"][optionnum] = []
|
||||
poll_list[polnum]["polldata"][optionnum].append(qqnum)
|
||||
writeback()
|
||||
return
|
||||
|
||||
poll = on_alconna(Alconna(
|
||||
"poll",
|
||||
Args["saying", MultiVar(str, '+'), Field(
|
||||
missing_tips=lambda: "参数错误。用法:发起投票 <投票标题> <选项1> <选项2> ..."
|
||||
)],
|
||||
), use_cmd_start=True, use_cmd_sep=False, skip_for_unmatch=False, aliases={"发起投票","createpoll"})
|
||||
@poll.handle()
|
||||
async def _(saying: list, event: Event):
|
||||
if (len(saying) < 3):
|
||||
await poll.send("请提供至少两个投票选项!")
|
||||
elif (len(saying) < 17):
|
||||
title = saying[0]
|
||||
saying.remove(title)
|
||||
options = {}
|
||||
for i in saying:
|
||||
options[saying.index(i)] = i
|
||||
qqid = event.get_user_id()
|
||||
result = await createpoll(title,qqid,options)
|
||||
await poll.send("已创建投票。回复 查看投票 "+str(result)+" 查看该投票。")
|
||||
else:
|
||||
await poll.send("投票选项太多了!请减少到15个选项以内。")
|
||||
|
||||
viewpoll = on_alconna(Alconna(
|
||||
"viewpoll",
|
||||
Args["saying", MultiVar(str, '+'), Field(
|
||||
missing_tips=lambda: "请指定投票ID或标题!。用法:查看投票 <投票ID或标题>"
|
||||
)],
|
||||
), use_cmd_start=True, use_cmd_sep=False, skip_for_unmatch=False, aliases={"查看投票"})
|
||||
@viewpoll.handle()
|
||||
async def _(saying: list):
|
||||
# 参数,投票ID或者标题
|
||||
# pollid_or_title = params[0]
|
||||
polldata = getpolldata(saying[0])
|
||||
# 被指定的投票项目
|
||||
thepoll = polldata[0]
|
||||
polnum = polldata[1]
|
||||
if polnum == -1:
|
||||
await viewpoll.send("该投票不存在!")
|
||||
else:
|
||||
# 检查投票是否已结束
|
||||
pollended = 0
|
||||
if time.time() > thepoll["expiry"]:
|
||||
pollended = 1
|
||||
# 回复内容
|
||||
reply = "投票:"+thepoll["title"]+" [ID: "+str(polnum)+"]"
|
||||
# 如果投票已结束
|
||||
if pollended:
|
||||
for i in thepoll["options"]:
|
||||
reply += "\n"
|
||||
# 检查该选项是否有人投票
|
||||
if i in thepoll["polldata"]:
|
||||
reply += "["+str(len(thepoll["polldata"][i]))+" 票]"
|
||||
else:
|
||||
reply += "[0 票]"
|
||||
reply += " "+thepoll["options"][i]
|
||||
reply += "\n\n此投票已结束。"
|
||||
else:
|
||||
for i in thepoll["options"]:
|
||||
reply += "\n"
|
||||
reply += "- "+thepoll["options"][i]
|
||||
# reply += "\n\n小提示:向bot私聊发送 /viewpoll "+str(polnum)+" 可查看已投票数哦!"
|
||||
reply += "\n\n发送 投票 "+str(polnum)+" <选项文本> 即可参与投票!"
|
||||
await viewpoll.send(reply)
|
||||
|
||||
vote = on_alconna(Alconna(
|
||||
"vote",
|
||||
Args["saying", MultiVar(str, '+'), Field(
|
||||
missing_tips=lambda: "参数错误。用法:投票 <投票ID/标题> <选项文本>"
|
||||
)],
|
||||
), use_cmd_start=True, use_cmd_sep=False, skip_for_unmatch=False, aliases={"投票","参与投票"})
|
||||
@vote.handle()
|
||||
async def _(saying: list, event: Event):
|
||||
if (len(saying) < 2):
|
||||
await vote.send("请指定投给哪一项!")
|
||||
else:
|
||||
polldata = getpolldata(saying[0])
|
||||
# 被指定的投票项目
|
||||
thepoll = polldata[0]
|
||||
polnum = polldata[1]
|
||||
if polnum == -1:
|
||||
await viewpoll.finish("没有找到这个投票!")
|
||||
# thepolldata = thepoll["polldata"]
|
||||
# 查找对应的投票项
|
||||
optionnum = -1
|
||||
for i in thepoll["options"]:
|
||||
if saying[1] == thepoll["options"][i]:
|
||||
optionnum = i
|
||||
break
|
||||
if optionnum == -1:
|
||||
reply = "此投票里面没有这一项!可用的选项有:"
|
||||
for i in thepoll["options"]:
|
||||
reply += "\n"
|
||||
reply += "- "+thepoll["options"][i]
|
||||
await viewpoll.send(reply)
|
||||
# 检查是否符合投票条件(该qq号是否已参与过投票、投票是否过期)
|
||||
elif time.time() > thepoll["expiry"]:
|
||||
await viewpoll.send("此投票已经结束!请发送 查看投票 "+polnum+" 查看结果。")
|
||||
elif str(event.get_user_id()) in str(thepoll["polldata"]):
|
||||
await viewpoll.send("你已参与过此投票!请在投票结束后发送 查看投票 "+polnum+" 查看结果。")
|
||||
# 写入项目
|
||||
else:
|
||||
await pollvote(polnum,optionnum,event.get_user_id())
|
||||
await viewpoll.send("投票成功!你投给了 "+saying[1])
|
||||
22
poetry.lock
generated
22
poetry.lock
generated
@ -2518,6 +2518,26 @@ files = [
|
||||
{file = "pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "qrcode"
|
||||
version = "8.2"
|
||||
description = "QR Code image generator"
|
||||
optional = false
|
||||
python-versions = "<4.0,>=3.9"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "qrcode-8.2-py3-none-any.whl", hash = "sha256:16e64e0716c14960108e85d853062c9e8bba5ca8252c0b4d0231b9df4060ff4f"},
|
||||
{file = "qrcode-8.2.tar.gz", hash = "sha256:35c3f2a4172b33136ab9f6b3ef1c00260dd2f66f858f24d88418a015f446506c"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
colorama = {version = "*", markers = "sys_platform == \"win32\""}
|
||||
|
||||
[package.extras]
|
||||
all = ["pillow (>=9.1.0)", "pypng"]
|
||||
pil = ["pillow (>=9.1.0)"]
|
||||
png = ["pypng"]
|
||||
|
||||
[[package]]
|
||||
name = "requests"
|
||||
version = "2.32.5"
|
||||
@ -3325,4 +3345,4 @@ type = ["pytest-mypy"]
|
||||
[metadata]
|
||||
lock-version = "2.1"
|
||||
python-versions = ">=3.12,<4.0"
|
||||
content-hash = "013942994a91012f285305194d73b6609fe71bbd214a63dce443877853dcd764"
|
||||
content-hash = "6fc63a138508a779d47346e0186b4c771ed17b10f278a0e094c6994c1d99a877"
|
||||
|
||||
@ -25,6 +25,7 @@ dependencies = [
|
||||
"ptimeparse (>=0.1.1,<0.2.0)",
|
||||
"skia-python (>=138.0,<139.0)",
|
||||
"nonebot-plugin-analysis-bilibili (>=2.8.1,<3.0.0)",
|
||||
"qrcode (>=8.2,<9.0)",
|
||||
]
|
||||
|
||||
[build-system]
|
||||
|
||||
Reference in New Issue
Block a user