feat: Ranking and help command support

This commit is contained in:
LWR 2023-02-07 19:26:54 +08:00
parent 148c57f5cd
commit a80f0c6af4
6 changed files with 458 additions and 3 deletions

View File

@ -12,3 +12,5 @@ import starbot.commands.builtin.data.user_data_total
import starbot.commands.builtin.disable_command
import starbot.commands.builtin.enable_command
import starbot.commands.builtin.help
import starbot.commands.builtin.ranking.ranking
import starbot.commands.builtin.ranking.ranking_double

View File

@ -0,0 +1,159 @@
from typing import Union
from graia.ariadne import Ariadne
from graia.ariadne.event.message import FriendMessage, GroupMessage
from graia.ariadne.message.chain import MessageChain
from graia.ariadne.message.element import Image
from graia.ariadne.message.parser.twilight import Twilight, FullMatch, UnionMatch
from graia.ariadne.model import Friend, Group
from graia.saya import Channel
from graia.saya.builtins.broadcast import ListenerSchema
from ...painter.PicGenerator import PicGenerator, Color
from ...utils import config, redis
prefix = config.get("COMMAND_PREFIX")
channel = Channel.current()
@channel.use(
ListenerSchema(
listening_events=[FriendMessage, GroupMessage],
inline_dispatchers=[Twilight(
FullMatch(prefix),
UnionMatch("帮助", "菜单", "功能", "命令", "指令", "help")
)],
)
)
async def _help(app: Ariadne, sender: Union[Friend, Group]):
disable_querys = ["DenyRoomData", "DenyRoomDataTotal", "DenyBind", "DenyUserData", "DenyUserDataTotal"]
disabled = [False] * 5
if isinstance(sender, Group):
disabled = [await redis.exists_disable_command(x, sender.id) for x in disable_querys]
width = 1000
height = 100000
pic = PicGenerator(width, height)
pic.set_pos(50, 50).draw_rounded_rectangle(0, 0, width, height, 35, Color.WHITE).copy_bottom(35)
pic.draw_chapter("StarBot 帮助")
pic.draw_text("")
pic.draw_section(f"1.{prefix}菜单")
commands = "".join([f"{prefix}{x}" for x in ["帮助", "菜单", "功能", "命令", "指令", "help"]])
pic.draw_text_multiline(50, ["命令: ", commands], [Color.RED, Color.BLACK])
pic.draw_tip("获取 Starbot 帮助和命令菜单")
pic.draw_section(f"2.{prefix}禁用命令")
commands = "".join([f"{prefix}{x} [命令名]" for x in ["禁用", "disable"]])
pic.draw_text_multiline(50, ["命令: ", commands], [Color.RED, Color.BLACK])
pic.draw_text(["示例: ", "禁用 直播间总数据"], [Color.RED, Color.BLACK])
pic.draw_tip("此命令仅群聊可用")
pic.draw_tip("可禁用的命令名: 绑定、直播间数据、直播间总数据、我的数据、我的总数据")
pic.draw_tip("命令禁用只针对本群,如有多群需同时禁用命令请每个群进行一次配置")
pic.draw_section(f"3.{prefix}启用命令")
commands = "".join([f"{prefix}{x} [命令名]" for x in ["启用", "enable"]])
pic.draw_text_multiline(50, ["命令: ", commands], [Color.RED, Color.BLACK])
pic.draw_text(["示例: ", "启用 直播间总数据"], [Color.RED, Color.BLACK])
pic.draw_tip("此命令仅群聊可用")
pic.draw_tip("用于禁用命令后解除禁用")
pic.draw_section(f"4.{prefix}直播间数据")
pic.draw_text_multiline(50, ["命令: ", f"{prefix}直播间数据"], [Color.RED, Color.BLACK])
if disabled[0]:
pic.draw_text("本群已禁用此命令", Color.RED)
pic.draw_tip("查询本直播间最近一场直播的数据")
pic.draw_section(f"5.{prefix}直播间总数据")
pic.draw_text_multiline(50, ["命令: ", f"{prefix}直播间总数据"], [Color.RED, Color.BLACK])
if disabled[1]:
pic.draw_text("本群已禁用此命令", Color.RED)
pic.draw_tip("查询本直播间自注册之日起的累计总数据")
pic.draw_section(f"6.{prefix}绑定")
commands = "".join([f"{prefix}{x} [UID]" for x in ["绑定", "bind"]])
pic.draw_text_multiline(50, ["命令: ", commands], [Color.RED, Color.BLACK])
pic.draw_text(["示例: ", "绑定 114514"], [Color.RED, Color.BLACK])
if disabled[2]:
pic.draw_text("本群已禁用此命令", Color.RED)
pic.draw_tip("将QQ号绑定至B站账号")
pic.draw_tip("绑定成功后即可查询自己在本直播间的数据")
pic.draw_tip("绑定后如需换绑直接使用新UID再次绑定即可")
pic.draw_section(f"7.{prefix}我的数据")
pic.draw_text_multiline(50, ["命令: ", f"{prefix}我的数据"], [Color.RED, Color.BLACK])
if disabled[3]:
pic.draw_text("本群已禁用此命令", Color.RED)
pic.draw_tip("查询自己在本直播间最近一场直播的数据、排名")
pic.draw_tip("需绑定B站账号后使用")
pic.draw_section(f"8.{prefix}我的总数据")
pic.draw_text_multiline(50, ["命令: ", f"{prefix}我的总数据"], [Color.RED, Color.BLACK])
if disabled[4]:
pic.draw_text("本群已禁用此命令", Color.RED)
pic.draw_tip("查询自己在本直播间自注册之日起的累计总数据、排名、占比")
pic.draw_tip("需绑定B站账号后使用")
pic.draw_section(f"9.{prefix}数据排行榜")
types = [
"弹幕排行", "弹幕总排行",
"盲盒排行", "盲盒总排行",
"盲盒盈亏排行", "盲盒盈亏总排行",
"礼物排行", "礼物总排行",
"SC排行", "SC总排行"
]
commands = "".join([f"{prefix}{x} <页码>" for x in types])
pic.draw_text_multiline(50, ["命令: ", commands], [Color.RED, Color.BLACK])
pic.draw_text(["示例: ", "弹幕排行、礼物总排行 3"], [Color.RED, Color.BLACK])
pic.draw_tip("查询本直播间的数据排行榜")
pic.draw_tip("xx排行指本直播间最近一场直播的数据排行榜")
pic.draw_tip("xx总排行指本直播间自注册之日起的累计总数据排行榜")
pic.draw_tip("不输入页码参数默认查询第一页")
pic.draw_section(f"10.{prefix}开播@我")
commands = "".join([f"{prefix}{x}" for x in ["开播@我", "直播@我"]])
pic.draw_text_multiline(50, ["命令: ", commands], [Color.RED, Color.BLACK])
pic.draw_tip("此命令仅群聊可用")
pic.draw_tip("本直播间开播时单独@自己")
pic.draw_tip("如配置了@全体成员会优先@全体成员")
pic.draw_tip("当没有配置@全体成员或@全体成员失败时会单独@\"开播@我\"名单中的群成员")
pic.draw_section(f"11.{prefix}取消开播@我")
commands = "".join([f"{prefix}{x}" for x in ["取消开播@我", "退出开播@我", "开播不@我", "开播别@我"]])
pic.draw_text_multiline(50, ["命令: ", commands], [Color.RED, Color.BLACK])
pic.draw_tip("此命令仅群聊可用")
pic.draw_tip("退出本群的\"开播@我\"名单")
pic.draw_section(f"12.{prefix}开播@名单")
commands = "".join([f"{prefix}{x}" for x in ["开播@名单", "开播@列表"]])
pic.draw_text_multiline(50, ["命令: ", commands], [Color.RED, Color.BLACK])
pic.draw_tip("此命令仅群聊可用")
pic.draw_tip("查询本群的\"开播@我\"名单")
pic.draw_section(f"13.{prefix}动态@我")
pic.draw_text_multiline(50, ["命令: ", f"{prefix}动态@我"], [Color.RED, Color.BLACK])
pic.draw_tip("此命令仅群聊可用")
pic.draw_tip("主播发布新动态时单独@自己")
pic.draw_tip("如配置了@全体成员会优先@全体成员")
pic.draw_tip("当没有配置@全体成员或@全体成员失败时会单独@\"动态@我\"名单中的群成员")
pic.draw_section(f"14.{prefix}取消动态@我")
commands = "".join([f"{prefix}{x}" for x in ["取消动态@我", "退出动态@我", "动态不@我", "动态别@我"]])
pic.draw_text_multiline(50, ["命令: ", commands], [Color.RED, Color.BLACK])
pic.draw_tip("此命令仅群聊可用")
pic.draw_tip("退出本群的\"动态@我\"名单")
pic.draw_section(f"15.{prefix}动态@名单")
commands = "".join([f"{prefix}{x}" for x in ["动态@名单", "动态@列表"]])
pic.draw_text_multiline(50, ["命令: ", commands], [Color.RED, Color.BLACK])
pic.draw_tip("此命令仅群聊可用")
pic.draw_tip("查询本群的\"动态@我\"名单")
# 底部版权信息,请务必保留此处
pic.draw_text_right(25, "Designed By StarBot", Color.GRAY)
pic.draw_text_right(25, "https://github.com/Starlwr/StarBot", Color.LINK)
pic.crop_and_paste_bottom()
await app.send_message(sender, MessageChain(Image(base64=pic.base64())))

View File

@ -0,0 +1,129 @@
import math
import time
from typing import Union
from graia.ariadne import Ariadne
from graia.ariadne.event.message import FriendMessage, GroupMessage
from graia.ariadne.message.chain import MessageChain
from graia.ariadne.message.element import Source, Image
from graia.ariadne.message.parser.twilight import Twilight, FullMatch, UnionMatch, ParamMatch, RegexResult, ResultValue
from graia.ariadne.model import Friend, Group
from graia.saya import Channel
from graia.saya.builtins.broadcast import ListenerSchema
from ....core.datasource import DataSource
from ....core.model import PushType
from ....painter.PicGenerator import PicGenerator, Color
from ....painter.RankingGenerator import RankingGenerator
from ....utils import config, redis
from ....utils.utils import remove_command_param_placeholder, get_unames_and_faces_by_uids, timestamp_format
prefix = config.get("COMMAND_PREFIX")
type_map = {
"弹幕": (redis.len_user_danmu_count, redis.rev_range_user_danmu_count, "弹幕", "弹幕"),
"弹幕总": (redis.len_user_danmu_all, redis.rev_range_user_danmu_all, "弹幕", "弹幕总"),
"盲盒": (redis.len_user_box_count, redis.rev_range_user_box_count, "盲盒", "盲盒"),
"宝盒": (redis.len_user_box_count, redis.rev_range_user_box_count, "盲盒", "盲盒"),
"盲盒总": (redis.len_user_box_all, redis.rev_range_user_box_all, "盲盒", "盲盒总"),
"宝盒总": (redis.len_user_box_all, redis.rev_range_user_box_all, "盲盒", "盲盒总"),
"礼物": (redis.len_user_gift_profit, redis.rev_range_user_gift_profit, "礼物", "礼物"),
"礼物总": (redis.len_user_gift_all, redis.rev_range_user_gift_all, "礼物", "礼物总"),
"SC": (redis.len_user_sc_profit, redis.rev_range_user_sc_profit, "SC", "SC"),
"sc": (redis.len_user_sc_profit, redis.rev_range_user_sc_profit, "SC", "SC"),
"醒目留言": (redis.len_user_sc_profit, redis.rev_range_user_sc_profit, "SC", "SC"),
"SC总": (redis.len_user_sc_all, redis.rev_range_user_sc_all, "SC", "SC总"),
"sc总": (redis.len_user_sc_all, redis.rev_range_user_sc_all, "SC", "SC总"),
"醒目留言总": (redis.len_user_sc_all, redis.rev_range_user_sc_all, "SC", "SC总")
}
channel = Channel.current()
@channel.use(
ListenerSchema(
listening_events=[FriendMessage, GroupMessage],
inline_dispatchers=[Twilight(
FullMatch(prefix),
"_type" @ ParamMatch(),
UnionMatch("", "排行", "排行榜"),
"page" @ ParamMatch(optional=True)
)],
)
)
async def ranking(app: Ariadne,
source: Source,
sender: Union[Friend, Group],
page: RegexResult,
_type: MessageChain = ResultValue()):
_type = _type.display
if _type not in type_map:
return
if page.matched:
page = remove_command_param_placeholder(page.result.display)
if not page.isdigit() or int(page) <= 0:
await app.send_message(sender, MessageChain("请输入正确的页码~"), quote=source)
return
page = int(page)
else:
page = 1
size = 10
start = size * (page - 1)
end = start + size - 1
datasource: DataSource = app.options["StarBotDataSource"]
ups = datasource.get_ups_by_target(sender.id, PushType.Group if isinstance(sender, Group) else PushType.Friend)
if not ups:
return
for up in ups:
length = await type_map[_type][0](up.room_id)
page_length = math.ceil(length / size)
if length == 0:
await app.send_message(sender, MessageChain(f"{up.uname} 的房间暂无{type_map[_type][2]}数据~"), quote=source)
return
if page > page_length:
await app.send_message(
sender,
MessageChain(f"{up.uname} 的房间{type_map[_type][3]}榜页码范围为 1 ~ {page_length}\n请重新输入正确的页码~"),
quote=source
)
return
data = await type_map[_type][1](up.room_id, start, end)
top_count = (await type_map[_type][1](up.room_id, 0, 0))[0][1]
uids = [x[0] for x in data]
counts = [x[1] for x in data]
unames, faces = await get_unames_and_faces_by_uids(uids)
width = 1000
height = 100000
margin = 50
pic = PicGenerator(width, height)
pic.set_pos(margin, margin).draw_rounded_rectangle(0, 0, width, height, 35, Color.WHITE).copy_bottom(35)
pic.draw_section(f"{up.uname} 房间的{type_map[_type][3]}排行")
pic.draw_text(f"{start + 1} 名 ~ 第 {start + len(uids)} 名 ( 第 {page} 页 / 共 {page_length} 页 )")
pic.draw_tip(f"UID: {up.uid} 房间号: {up.room_id}")
pic.draw_tip(f"查询时间: {timestamp_format(int(time.time()), '%Y/%m/%d %H:%M:%S')}")
if page != page_length:
pic.draw_tip(f"继续查看下一页请发送 \"{prefix}{type_map[_type][3]}{page + 1}\"")
pic.draw_text("")
pic.draw_img_alpha(
RankingGenerator.get_ranking(pic.row_space, faces, unames, counts, pic.width - (margin * 2), top_count)
)
# 底部版权信息,请务必保留此处
pic.draw_text("")
pic.draw_text_right(25, "Designed By StarBot", Color.GRAY)
pic.draw_text_right(25, "https://github.com/Starlwr/StarBot", Color.LINK)
pic.crop_and_paste_bottom()
await app.send_message(sender, MessageChain(Image(base64=pic.base64())))

View File

@ -0,0 +1,124 @@
import math
import time
from typing import Union
from graia.ariadne import Ariadne
from graia.ariadne.event.message import FriendMessage, GroupMessage
from graia.ariadne.message.chain import MessageChain
from graia.ariadne.message.element import Source, Image
from graia.ariadne.message.parser.twilight import Twilight, FullMatch, UnionMatch, ParamMatch, RegexResult, ResultValue
from graia.ariadne.model import Friend, Group
from graia.saya import Channel
from graia.saya.builtins.broadcast import ListenerSchema
from ....core.datasource import DataSource
from ....core.model import PushType
from ....painter.PicGenerator import PicGenerator, Color
from ....painter.RankingGenerator import RankingGenerator
from ....utils import config, redis
from ....utils.utils import remove_command_param_placeholder, get_unames_and_faces_by_uids, timestamp_format
prefix = config.get("COMMAND_PREFIX")
type_map = {
"盲盒盈亏": (redis.len_user_box_count, redis.rev_range_user_box_profit, "盲盒", "盲盒盈亏"),
"宝盒盈亏": (redis.len_user_box_count, redis.rev_range_user_box_profit, "盲盒", "盲盒盈亏"),
"盲盒盈亏总": (redis.len_user_box_all, redis.rev_range_user_box_profit_all, "盲盒", "盲盒盈亏总"),
"宝盒盈亏总": (redis.len_user_box_all, redis.rev_range_user_box_profit_all, "盲盒", "盲盒盈亏总")
}
channel = Channel.current()
@channel.use(
ListenerSchema(
listening_events=[FriendMessage, GroupMessage],
inline_dispatchers=[Twilight(
FullMatch(prefix),
"_type" @ ParamMatch(),
UnionMatch("", "排行", "排行榜"),
"page" @ ParamMatch(optional=True)
)],
)
)
async def ranking_double(app: Ariadne,
source: Source,
sender: Union[Friend, Group],
page: RegexResult,
_type: MessageChain = ResultValue()):
_type = _type.display
if _type not in type_map:
return
if page.matched:
page = remove_command_param_placeholder(page.result.display)
if not page.isdigit() or int(page) <= 0:
await app.send_message(sender, MessageChain("请输入正确的页码~"), quote=source)
return
page = int(page)
else:
page = 1
size = 10
start = size * (page - 1)
end = start + size - 1
datasource: DataSource = app.options["StarBotDataSource"]
ups = datasource.get_ups_by_target(sender.id, PushType.Group if isinstance(sender, Group) else PushType.Friend)
if not ups:
return
for up in ups:
length = await type_map[_type][0](up.room_id)
page_length = math.ceil(length / size)
if length == 0:
await app.send_message(sender, MessageChain(f"{up.uname} 的房间暂无{type_map[_type][2]}数据~"), quote=source)
return
if page > page_length:
await app.send_message(
sender,
MessageChain(f"{up.uname} 的房间{type_map[_type][3]}榜页码范围为 1 ~ {page_length}\n请重新输入正确的页码~"),
quote=source
)
return
data = await type_map[_type][1](up.room_id, start, end)
top_count = max(
(await type_map[_type][1](up.room_id, 0, 0))[0][1],
abs((await type_map[_type][1](up.room_id, -1, -1))[0][1])
)
uids = [x[0] for x in data]
counts = [x[1] for x in data]
unames, faces = await get_unames_and_faces_by_uids(uids)
width = 1000
height = 100000
margin = 50
pic = PicGenerator(width, height)
pic.set_pos(margin, margin).draw_rounded_rectangle(0, 0, width, height, 35, Color.WHITE).copy_bottom(35)
pic.draw_section(f"{up.uname} 房间的{type_map[_type][3]}排行")
pic.draw_text(f"{start + 1} 名 ~ 第 {start + len(uids)} 名 ( 第 {page} 页 / 共 {page_length} 页 )")
pic.draw_tip(f"UID: {up.uid} 房间号: {up.room_id}")
pic.draw_tip(f"查询时间: {timestamp_format(int(time.time()), '%Y/%m/%d %H:%M:%S')}")
if page != page_length:
pic.draw_tip(f"继续查看下一页请发送 \"{prefix}{type_map[_type][3]}{page + 1}\"")
pic.draw_text("")
pic.draw_img_alpha(
RankingGenerator.get_double_ranking(
pic.row_space, faces, unames, counts, pic.width - (margin * 2), top_count
)
)
# 底部版权信息,请务必保留此处
pic.draw_text("")
pic.draw_text_right(25, "Designed By StarBot", Color.GRAY)
pic.draw_text_right(25, "https://github.com/Starlwr/StarBot", Color.LINK)
pic.crop_and_paste_bottom()
await app.send_message(sender, MessageChain(Image(base64=pic.base64())))

View File

@ -1,4 +1,4 @@
from typing import Union, Tuple, List
from typing import Optional, Union, Tuple, List
from PIL import Image, ImageDraw
@ -69,6 +69,7 @@ class RankingGenerator:
unames: List[str],
counts: Union[List[int], List[float]],
width: int,
top_count: Optional[Union[int, float]] = None,
start_color: Union[Color, Tuple[int, int, int]] = Color.DEEPBLUE,
end_color: Union[Color, Tuple[int, int, int]] = Color.LIGHTBLUE) -> Image:
"""
@ -80,6 +81,7 @@ class RankingGenerator:
unames: 昵称列表按照数量列表降序排序
counts: 数量列表降序排序
width: 排行榜图片宽度
top_count: 第一名数量后续排行条长度会基于此数量计算长度默认自动取数量列表中第一名
start_color: 排行条渐变起始颜色默认深蓝色 (57, 119, 230)
end_color: 排行条渐变终止颜色默认浅蓝色 (55, 187, 248)
"""
@ -93,7 +95,8 @@ class RankingGenerator:
bar_x = face_size - offset
top_bar_width = width - face_size + offset
top_count = counts[0]
if top_count is None:
top_count = counts[0]
chart = PicGenerator(width, (face_size * count) + (row_space * (count - 1)))
chart.set_row_space(row_space)
@ -116,6 +119,7 @@ class RankingGenerator:
unames: List[str],
counts: Union[List[int], List[float]],
width: int,
top_count: Optional[Union[int, float]] = None,
start_color: Union[Color, Tuple[int, int, int]] = Color.DEEPRED,
end_color: Union[Color, Tuple[int, int, int]] = Color.LIGHTRED,
reverse_start_color: Union[Color, Tuple[int, int, int]] = Color.DEEPGREEN,
@ -129,6 +133,7 @@ class RankingGenerator:
unames: 昵称列表按照数量列表降序排序
counts: 数量列表降序排序
width: 排行榜图片宽度
top_count: 第一名数量后续排行条长度会基于此数量计算长度默认自动取数量列表中第一名
start_color: 正向排行条渐变起始颜色数量为正时使用默认深红色 (57, 119, 230)
end_color: 正向排行条渐变终止颜色数量为正时使用默认浅红色 (55, 187, 248)
reverse_start_color: 反向排行条渐变起始颜色数量为负时使用默认深绿色 (57, 119, 230)
@ -146,7 +151,8 @@ class RankingGenerator:
bar_x = face_x + face_size - offset
reverse_bar_x = face_x + offset
top_bar_width = (width - face_size) / 2 + offset
top_count = max(max(counts), abs(min(counts)))
if top_count is None:
top_count = max(max(counts), abs(min(counts)))
chart = PicGenerator(width, (face_size * count) + (row_space * (count - 1)))
chart.set_row_space(row_space)

View File

@ -333,6 +333,13 @@ async def range_user_danmu_all(room_id: int, start: int = 0, end: int = -1) -> L
return result
async def rev_range_user_danmu_all(room_id: int, start: int = 0, end: int = -1) -> List[Tuple[str, int]]:
await zunionstore(f"TempDanmuTotal:{room_id}", [f"UserDanmuCount:{room_id}", f"UserDanmuTotal:{room_id}"])
result = await zrevrangewithscoresi(f"TempDanmuTotal:{room_id}", start, end)
await delete(f"TempDanmuTotal:{room_id}")
return result
# 房间弹幕记录
async def get_room_danmu(room_id: int) -> List[str]:
@ -447,6 +454,13 @@ async def range_user_box_all(room_id: int, start: int = 0, end: int = -1) -> Lis
return result
async def rev_range_user_box_all(room_id: int, start: int = 0, end: int = -1) -> List[Tuple[str, int]]:
await zunionstore(f"TempBoxTotal:{room_id}", [f"UserBoxCount:{room_id}", f"UserBoxTotal:{room_id}"])
result = await zrevrangewithscoresi(f"TempBoxTotal:{room_id}", start, end)
await delete(f"TempBoxTotal:{room_id}")
return result
# 房间盲盒盈亏
async def get_room_box_profit(room_id: int) -> float:
@ -524,6 +538,13 @@ async def range_user_box_profit_all(room_id: int, start: int = 0, end: int = -1)
return result
async def rev_range_user_box_profit_all(room_id: int, start: int = 0, end: int = -1) -> List[Tuple[str, float]]:
await zunionstore(f"TempBoxProfitTotal:{room_id}", [f"UserBoxProfit:{room_id}", f"UserBoxProfitTotal:{room_id}"])
result = await zrevrangewithscoresf1(f"TempBoxProfitTotal:{room_id}", start, end)
await delete(f"TempBoxProfitTotal:{room_id}")
return result
# 房间盲盒盈亏记录,用于绘制直播报告中盲盒盈亏曲线图
async def get_room_box_profit_record(room_id: int) -> List[float]:
@ -654,6 +675,13 @@ async def range_user_gift_all(room_id: int, start: int = 0, end: int = -1) -> Li
return result
async def rev_range_user_gift_all(room_id: int, start: int = 0, end: int = -1) -> List[Tuple[str, float]]:
await zunionstore(f"TempGiftTotal:{room_id}", [f"UserGiftProfit:{room_id}", f"UserGiftTotal:{room_id}"])
result = await zrevrangewithscoresf1(f"TempGiftTotal:{room_id}", start, end)
await delete(f"TempGiftTotal:{room_id}")
return result
# 房间礼物时间分布
async def get_room_gift_time(room_id: int) -> List[Tuple[str, float]]:
@ -754,6 +782,13 @@ async def range_user_sc_all(room_id: int, start: int = 0, end: int = -1) -> List
return result
async def rev_range_user_sc_all(room_id: int, start: int = 0, end: int = -1) -> List[Tuple[str, int]]:
await zunionstore(f"TempScTotal:{room_id}", [f"UserScProfit:{room_id}", f"UserScTotal:{room_id}"])
result = await zrevrangewithscoresi(f"TempScTotal:{room_id}", start, end)
await delete(f"TempScTotal:{room_id}")
return result
# 房间 SC 时间分布
async def get_room_sc_time(room_id: int) -> List[Tuple[str, int]]: