Compare commits
2 Commits
d4e3c49ef2
..
master
| Author | SHA1 | Date | |
|---|---|---|---|
| d307726a58 | |||
| 25c64bb338 |
@@ -19,3 +19,6 @@
|
|||||||
[submodule "src/modules/pluscampaign"]
|
[submodule "src/modules/pluscampaign"]
|
||||||
path = src/modules/pluscampaign
|
path = src/modules/pluscampaign
|
||||||
url = https://git.thewisewolf.dev/CarmiCoven/pluscampaign-plugin.git
|
url = https://git.thewisewolf.dev/CarmiCoven/pluscampaign-plugin.git
|
||||||
|
[submodule "src/modules/tracker"]
|
||||||
|
path = src/modules/tracker
|
||||||
|
url = https://git.thewisewolf.dev/HoloTech/twitch-eventtracker-plugin.git
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ active = [
|
|||||||
".messagelogger",
|
".messagelogger",
|
||||||
".voicelog",
|
".voicelog",
|
||||||
".yarn",
|
".yarn",
|
||||||
|
".tracker",
|
||||||
".pluscampaign",
|
".pluscampaign",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
Submodule
+1
Submodule src/modules/tracker added at 2f4778d0b8
+194
-2
@@ -1,4 +1,5 @@
|
|||||||
from typing import Literal
|
from pathlib import Path
|
||||||
|
from typing import Literal, Optional
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
import datetime as dt
|
import datetime as dt
|
||||||
from datetime import datetime, timedelta, UTC
|
from datetime import datetime, timedelta, UTC
|
||||||
@@ -6,7 +7,7 @@ from datetime import datetime, timedelta, UTC
|
|||||||
from data.queries import ORDER
|
from data.queries import ORDER
|
||||||
import discord
|
import discord
|
||||||
from discord.ext import commands as cmds
|
from discord.ext import commands as cmds
|
||||||
from discord import app_commands as appcmds
|
from discord import Attachment, app_commands as appcmds
|
||||||
|
|
||||||
from meta import LionBot, LionCog, LionContext
|
from meta import LionBot, LionCog, LionContext
|
||||||
from meta.logger import log_wrap
|
from meta.logger import log_wrap
|
||||||
@@ -132,3 +133,194 @@ class YarnCog(LionCog):
|
|||||||
pages = paginate_list(lb_strings, block_length=page_len, title=title)
|
pages = paginate_list(lb_strings, block_length=page_len, title=title)
|
||||||
|
|
||||||
await pager(ctx, pages)
|
await pager(ctx, pages)
|
||||||
|
|
||||||
|
@cmds.hybrid_command(name="topvoice")
|
||||||
|
async def topvoice_cmd(self, ctx):
|
||||||
|
"""
|
||||||
|
Show top voice members by total time.
|
||||||
|
"""
|
||||||
|
target_channelid = 1383707078740279366
|
||||||
|
since_stamp = 1769832959
|
||||||
|
|
||||||
|
voicelogger = ctx.bot.get_cog("VoiceLogCog")
|
||||||
|
session_data = voicelogger.data.voicelog_sessions
|
||||||
|
|
||||||
|
query = (
|
||||||
|
session_data.select_where(
|
||||||
|
VoiceLogSession.joined_at
|
||||||
|
>= datetime.fromtimestamp(since_stamp, tz=UTC),
|
||||||
|
guildid=ctx.guild.id,
|
||||||
|
channelid=target_channelid,
|
||||||
|
)
|
||||||
|
.select(
|
||||||
|
userid="userid",
|
||||||
|
total_time="SUM(COALESCE(duration, EXTRACT(EPOCH FROM (NOW() - joined_at))))",
|
||||||
|
)
|
||||||
|
.order_by("total_time", ORDER.DESC)
|
||||||
|
.group_by("userid")
|
||||||
|
.with_no_adapter()
|
||||||
|
)
|
||||||
|
leaderboard = [(row["userid"], int(row["total_time"])) for row in await query]
|
||||||
|
|
||||||
|
# Format for display and pager
|
||||||
|
# First collect names
|
||||||
|
names = {}
|
||||||
|
for uid, _ in leaderboard:
|
||||||
|
user = ctx.guild.get_member(uid)
|
||||||
|
if user is None:
|
||||||
|
try:
|
||||||
|
user = await ctx.guild.fetch_member(uid)
|
||||||
|
except discord.NotFound:
|
||||||
|
user = None
|
||||||
|
names[uid] = user.display_name if user else str(uid)
|
||||||
|
|
||||||
|
lb_strings = []
|
||||||
|
max_name_len = min((30, max(len(name) for name in names.values())))
|
||||||
|
for i, (uid, total) in enumerate(leaderboard):
|
||||||
|
lb_strings.append(
|
||||||
|
"{:<{}}\t{:<9}".format(
|
||||||
|
names[uid], max_name_len, strfdur(total, short=False)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
page_len = 20
|
||||||
|
title = "Voice Leaderboard"
|
||||||
|
pages = paginate_list(lb_strings, block_length=page_len, title=title)
|
||||||
|
|
||||||
|
await pager(ctx, pages)
|
||||||
|
|
||||||
|
@cmds.hybrid_command(name="topmoomin")
|
||||||
|
async def topmoomin_cmd(self, ctx):
|
||||||
|
target_channelid = 1383707078740279366
|
||||||
|
since_stamp = 1777960800
|
||||||
|
|
||||||
|
# Build timestamps of all moomin times since the start
|
||||||
|
# Reverse time order
|
||||||
|
moomin_periods = []
|
||||||
|
last_moomin_start = 1785823200
|
||||||
|
moomin_dur = 60 * 30
|
||||||
|
|
||||||
|
mstart = last_moomin_start
|
||||||
|
while mstart >= since_stamp:
|
||||||
|
period = (mstart, mstart + moomin_dur)
|
||||||
|
moomin_periods.append(period)
|
||||||
|
mstart -= 24 * 60 * 60
|
||||||
|
|
||||||
|
# Get all voice sessions
|
||||||
|
|
||||||
|
voicelogger = ctx.bot.get_cog("VoiceLogCog")
|
||||||
|
session_data = voicelogger.data.voicelog_sessions
|
||||||
|
|
||||||
|
query = (
|
||||||
|
session_data.select_where(
|
||||||
|
VoiceLogSession.joined_at
|
||||||
|
>= datetime.fromtimestamp(since_stamp, tz=UTC),
|
||||||
|
guildid=ctx.guild.id,
|
||||||
|
channelid=target_channelid,
|
||||||
|
)
|
||||||
|
.select("userid", "joined_at", "duration")
|
||||||
|
.order_by("joined_at", ORDER.DESC)
|
||||||
|
.with_no_adapter()
|
||||||
|
)
|
||||||
|
rows = await query
|
||||||
|
|
||||||
|
# For each session, intersect it with all the moomin times, sum the intersection seconds. Key by userid
|
||||||
|
moomin_leaderboard = defaultdict(int)
|
||||||
|
for row in rows:
|
||||||
|
start_stamp = row["joined_at"].timestamp()
|
||||||
|
if row["duration"]:
|
||||||
|
end_stamp = start_stamp + row["duration"]
|
||||||
|
else:
|
||||||
|
end_stamp = utc_now().timestamp()
|
||||||
|
|
||||||
|
# Intersection
|
||||||
|
for mstart, mend in moomin_periods:
|
||||||
|
if mend < start_stamp:
|
||||||
|
# Moomin periods go backwards
|
||||||
|
# Stop looking if the period ended before this voice session started
|
||||||
|
break
|
||||||
|
# Guarantee: mend >= start_stamp
|
||||||
|
if mstart <= end_stamp:
|
||||||
|
# Period starts before the end of the voice session
|
||||||
|
# and ends after the start of the session
|
||||||
|
intersection_start = max(start_stamp, mstart)
|
||||||
|
intersection_end = min(end_stamp, mend)
|
||||||
|
diff = intersection_end - intersection_start
|
||||||
|
moomin_leaderboard[row["userid"]] += int(diff)
|
||||||
|
else:
|
||||||
|
# Period starts after the end of the voice session, ignore
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Format for display and pager
|
||||||
|
leaderboard = sorted(
|
||||||
|
moomin_leaderboard.items(), key=lambda p: p[1], reverse=True
|
||||||
|
)
|
||||||
|
|
||||||
|
# First collect names
|
||||||
|
names = {}
|
||||||
|
users = {}
|
||||||
|
for uid, _ in leaderboard:
|
||||||
|
user = ctx.guild.get_member(uid)
|
||||||
|
if user is None:
|
||||||
|
try:
|
||||||
|
user = await ctx.guild.fetch_member(uid)
|
||||||
|
except discord.NotFound:
|
||||||
|
user = None
|
||||||
|
names[uid] = user.display_name if user else str(uid)
|
||||||
|
users[uid] = user
|
||||||
|
|
||||||
|
lb_strings = []
|
||||||
|
max_name_len = min((30, max(len(name) for name in names.values())))
|
||||||
|
for i, (uid, total) in enumerate(leaderboard):
|
||||||
|
lb_strings.append(
|
||||||
|
"{:<{}}\t{:<9}".format(
|
||||||
|
names[uid], max_name_len, strfdur(total, short=False)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
page_len = 20
|
||||||
|
title = "Moomin Leaderboard"
|
||||||
|
pages = paginate_list(lb_strings, block_length=page_len, title=title)
|
||||||
|
await pager(ctx, pages)
|
||||||
|
|
||||||
|
if ctx.author.guild_permissions.administrator:
|
||||||
|
threshold = 20 * 60
|
||||||
|
|
||||||
|
role = ctx.guild.get_role(1534089417612857424)
|
||||||
|
if not role:
|
||||||
|
await ctx.reply("Couldn't find the role!")
|
||||||
|
return
|
||||||
|
earned_users = []
|
||||||
|
for uid, dur in leaderboard:
|
||||||
|
if dur >= threshold:
|
||||||
|
if user := users.get(uid):
|
||||||
|
earned_users.append(user)
|
||||||
|
if role not in user.roles:
|
||||||
|
await user.add_roles(role, reason=f"Watched moomin for {dur}")
|
||||||
|
await ctx.reply(
|
||||||
|
f"Added moomin role to: {', '.join(u.mention for u in earned_users)} ",
|
||||||
|
allowed_mentions=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def _upload_file(self, file: discord.Attachment, filename: str):
|
||||||
|
filedir = Path("/extension/www/lilac")
|
||||||
|
target = filedir / filename
|
||||||
|
|
||||||
|
await file.save(target)
|
||||||
|
return f"https://lilac.thewisewolf.dev/provides/{filename}"
|
||||||
|
|
||||||
|
@cmds.hybrid_group(name="upload")
|
||||||
|
@appcmds.default_permissions(administrator=True)
|
||||||
|
async def upload_group(self, ctx):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@upload_group.command(name="file")
|
||||||
|
@appcmds.default_permissions(administrator=True)
|
||||||
|
async def upload_file_group(
|
||||||
|
self, ctx, file: discord.Attachment, filename: Optional[str] = None
|
||||||
|
):
|
||||||
|
await ctx.interaction.response.defer(thinking=True, ephemeral=True)
|
||||||
|
url = await self._upload_file(file, filename or file.filename)
|
||||||
|
await ctx.reply(
|
||||||
|
embed=discord.Embed(description=f"File now available at: {url}")
|
||||||
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user