Skip to content

Commit 60d1339

Browse files
committed
Removal of admin report tickets as they are not functional, better management of ties in video voting
1 parent 22ea013 commit 60d1339

6 files changed

Lines changed: 83 additions & 63 deletions

File tree

.gitignore

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ wheels/
1010
.venv
1111

1212
# development files
13-
# private*.* # deprecated
14-
# *.db # deprecated
1513
dev/
16-
.env
14+
.env
15+
repulsbot.code-workspace

src/cogs/about_cog.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,6 @@ async def avatar(self, ctx: commands.Context, member: discord.Member):
106106
else:
107107
embed.add_field(name="This user has no avatar", value="*nothing to display...*")
108108

109-
embed.set_footer(text=FOOTER_EMBED)
110109
await ctx.send(embed=embed)
111110

112111
@commands.hybrid_command(name="membercount", description="Get the server member count")

src/cogs/tickets_cog.py

Lines changed: 14 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,19 @@
2020
IDs.serverRoles.CONTRIBUTOR
2121
]
2222

23-
TICKETS_CATEGORY_NAME = "Tickets"
2423
TICKET_TYPES = [
2524
# label | description | abbreviation
2625
("In-game report", "Hackers and chat reports", "ing-rep"),
2726
("Discord report", "Discord issues/report a member", "dis-rep"),
2827
("Role related", "Applications/promotion about roles", "rol"),
29-
("Admin report", "Report an admin's behavior", "admin"),
3028
("Other", "Other inquiries or problems", "other")
3129
]
3230

3331
OPEN_TICKET_TITLE = "🎟️ Need help ? Open a Ticket"
3432
OPEN_TICKET_MSG = """
3533
Simply click on the type of ticket you want to open **in the selector below**, and fill up the information needed (send your images and video after creating the ticket).\n
3634
It will create a private channel between you and **the moderation team**. This way, you can make a report, request a role, or anything else.\n
37-
**Only create a ticket if absolutely necessary!** If you need urgent assistance, please ping or send a DM to an administrator. Before creating a ticket, check if the answer to your question is not in the server FAQs (e.g., the requirements for roles are indicated there)! To report a game bug, you can use the channel https://discord.com/channels/603655329120518223/1076163933213311067!
35+
**Only create a ticket if absolutely necessary!** If you need urgent assistance, please ping or send a DM to an admin. Before creating a ticket, check if the answer to your question is not in the server FAQs (e.g., the requirements for roles are indicated there)! To report a game bug, you can use https://discord.com/channels/603655329120518223/1076163933213311067!
3836
"""
3937

4038
class GoToTicketButton(discord.ui.View):
@@ -73,24 +71,28 @@ async def on_submit(self, interaction: discord.Interaction):
7371
author = interaction.user
7472

7573
# creation of the private channel
76-
category = await self._get_tickets_category(guild)
74+
category = discord.utils.get(guild.categories, id=IDs.serverChannel.TICKETS_CATEGORY)
7775
channel_name = self._build_ticket_channel_name()
7876
overwrites = self._build_ticket_overwrites(guild, author)
7977

8078
ticket_channel = await guild.create_text_channel(
8179
channel_name, category=category, overwrites=overwrites,
82-
topic=f"Ticket by {author} **{self._get_ticket_label()}** ・ {self.title_input.value}"
80+
topic=f"🎟️ **{self._get_ticket_label()}** ・ {self.title_input.value}"
8381
)
8482

8583
# first channel's message
8684
embed = discord.Embed(
87-
title=f"🎟️ {self.title_input.value}",
85+
title=f"{self.title_input.value}",
8886
description=self.description_input.value,
89-
color=discord.Color.dark_blue()
87+
color=discord.Color.blue()
88+
)
89+
embed.set_author(
90+
name=author.display_name,
91+
icon_url=author.display_avatar.url,
9092
)
91-
embed.set_footer(text=f"Ticket type {self._get_ticket_label()}")
93+
embed.set_footer(text=f"Ticket type \"{self._get_ticket_label()}\"")
9294

93-
await ticket_channel.send(content=f"Opened by {author.mention}", embed=embed)
95+
await ticket_channel.send(embed=embed)
9496
await interaction.response.send_message(
9597
f"{DefaultEmojis.CHECK} Your ticket has been created: {ticket_channel.mention}",
9698
view=GoToTicketButton(ticket_channel),
@@ -108,20 +110,14 @@ async def on_submit(self, interaction: discord.Interaction):
108110
await interaction.response.send_message(f":x: {error_msg}{ASK_HELP}", ephemeral=True)
109111

110112
def _build_ticket_overwrites(self, guild: discord.Guild, author: discord.Member) -> dict:
113+
# permissions to the bot, ticket author and authorized members to view the private channel
111114
overwrites = {
112115
guild.default_role: discord.PermissionOverwrite(view_channel=False),
113116
author: PERMS_ACCESS_GRANTED,
114117
guild.me: PERMS_ACCESS_GRANTED
115118
}
116119

117-
# visible only to the server owner and author
118-
if self.ticket_type_abbr == "admin":
119-
owner = guild.get_member(guild.owner_id)
120-
if owner:
121-
overwrites[owner] = PERMS_ACCESS_GRANTED
122-
# permissions to the ticket author and authorized members to view the private channel
123-
else:
124-
for role_id in AUTHORIZED_MEMBERS:
120+
for role_id in AUTHORIZED_MEMBERS:
125121
role = guild.get_role(role_id)
126122
if role:
127123
overwrites[role] = PERMS_ACCESS_GRANTED
@@ -132,14 +128,6 @@ def _build_ticket_channel_name(self) -> str:
132128
code = "".join(random.choices(string.ascii_lowercase + string.digits, k=6))
133129
return f"{self.ticket_type_abbr.lower()}-{code}"
134130

135-
async def _get_tickets_category(self, guild: discord.Guild):
136-
category = discord.utils.get(guild.categories, name=TICKETS_CATEGORY_NAME)
137-
if category:
138-
return category
139-
else:
140-
overwrites = {guild.default_role: discord.PermissionOverwrite(view_channel=False)}
141-
return await guild.create_category(TICKETS_CATEGORY_NAME, overwrites=overwrites)
142-
143131
def _get_ticket_label(self) -> str:
144132
return next((label for label, _, abbr in TICKET_TYPES if abbr == self.ticket_type_abbr), "Other")
145133

@@ -196,7 +184,7 @@ def __init__(self, bot: commands.Bot):
196184

197185
@commands.hybrid_command(name="close_ticket", description="Close current ticket (only available in a ticket)")
198186
async def close_ticket(self, ctx: commands.Context):
199-
if ctx.channel.category and ctx.channel.category.name == TICKETS_CATEGORY_NAME:
187+
if ctx.channel.category and ctx.channel.category.id == IDs.serverChannel.TICKETS_CATEGORY:
200188
view = CancelCloseView()
201189
embed = discord.Embed(
202190
title=f"🔒 Ticket will be closed in {SECONDS_BEFORE_TICKET_CLOSING}s...",

src/cogs/vote_cog.py

Lines changed: 61 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,17 @@
22
from discord.ext import tasks, commands
33
import re
44
import aiohttp
5+
import random
56
# bot files
67
from utils import (
78
send_hidden_message,
8-
hoursdelta
9+
hoursdelta,
10+
nl
911
)
1012

1113
from cogs.cogs_info import CogsNames
1214
from constants import (
1315
DefaultEmojis,
14-
Links,
1516
PrivateData,
1617
IDs,
1718
ASK_HELP,
@@ -26,13 +27,14 @@
2627
re.IGNORECASE
2728
)
2829

29-
VOTE_HOURS = 24
30+
VOTE_HOURS = 48
3031
SUCCESS_CODE = 200
32+
REACTION = DefaultEmojis.CHECK
3133

32-
FEATURED_VIDEO_MSG = """
33-
(And you, do you want your video to appear on the game's main page? Then hurry up and post the link here,
34-
and cross your fingers that the community votes for your message with the reaction {reaction} just below!
35-
***I come and check the best video every {time} hours, you have every chance!***)
34+
FEATURED_VIDEO_MSG = f"""
35+
And you, do you want your video to appear on the game's main page?
36+
Then hurry up and post the link here, and cross your fingers...
37+
I come and check the best video every {VOTE_HOURS} hours, you have every chance!
3638
"""
3739

3840
class YouTubeLink(commands.Converter):
@@ -80,47 +82,74 @@ async def check_better_video(self):
8082
if not video_channel:
8183
return
8284

83-
better_video_msg = None
85+
better_video_msgs = []
8486
last_better_votes = 0
87+
after_time = hoursdelta(5 * 24) # 5 days
8588

86-
async for message in video_channel.history(limit=50, after=hoursdelta(VOTE_HOURS)):
89+
async for message in video_channel.history(limit=50, after=after_time):
8790
if not re.search(YOUTUBE_REGEX, message.content):
8891
continue # pass all messages without youtube links
8992

9093
# update message cache (https://github.com/Rapptz/discord.py/issues/861)
9194
msg = await video_channel.fetch_message(message.id)
9295
for reaction in msg.reactions:
93-
if str(reaction.emoji) == DefaultEmojis.CHECK:
96+
if str(reaction.emoji) == REACTION:
9497
vote = reaction.count
9598
if vote > last_better_votes:
9699
last_better_votes = vote
97-
better_video_msg = msg
100+
better_video_msgs = [msg]
101+
elif vote == last_better_votes:
102+
better_video_msgs.append(msg)
98103
break
99104

100-
await self.process_winner(video_channel=video_channel, msg=better_video_msg, vote_count=last_better_votes)
105+
await self.process_winner(video_channel, better_video_msgs, last_better_votes)
101106

102-
async def process_winner(self, video_channel: discord.TextChannel, msg: discord.Message, vote_count: int):
103-
if msg and vote_count > 0:
104-
embed = discord.Embed(
105-
title="New featured video! 🎉",
106-
color=discord.Color.dark_blue(),
107-
timestamp=discord.utils.utcnow(),
108-
description=FEATURED_VIDEO_MSG.format(reaction=DefaultEmojis.CHECK, time=VOTE_HOURS).replace('\n', ' ').strip()
109-
)
110-
embed.add_field(name="Watch it now!", value=msg.jump_url)
107+
async def process_winner(self, video_channel: discord.abc.Messageable, messages: list[discord.Message], vote_count: int):
108+
embed = discord.Embed(
109+
title="New featured video! 🎉",
110+
color=discord.Color.brand_red(),
111+
timestamp=discord.utils.utcnow()
112+
)
113+
# no videos to send, notify youtubers
114+
if len(messages) < 1:
115+
embed.title = "I couldn't find any videos to display on the game's homepage 🫤..."
116+
embed.description = f"Become a <@&{IDs.serverRoles.YOUTUBER}> by meeting [these conditions](https://discord.com/channels/603655329120518223/733177088961544202/1389263121591570496), and post your first videos! 🚀"
117+
embed.timestamp = None
118+
# one or more videos found to send
119+
else:
120+
winner: discord.Message = None
121+
# only one winning video
122+
if len(messages) == 1:
123+
winner = messages[0]
124+
embed.add_field(
125+
name="Watch it now!",
126+
value=f"🎬 [Click here to watch the video]({winner.jump_url}), by {winner.author.mention}!",
127+
inline=False
128+
)
129+
embed.set_footer(text=nl(FEATURED_VIDEO_MSG))
130+
# case of equality
131+
else:
132+
embed.title = "👏 Bravo! Several videos are tied!"
133+
embed.description = f"The following videos come in first with {vote_count} votes each!"
111134

112-
match = re.search(YOUTUBE_REGEX, msg.content)
135+
for idx, m in enumerate(messages, 1):
136+
embed.add_field(name="", value=f"{idx}. [Video]({m.jump_url}) of {m.author.mention}", inline=False)
137+
138+
winner = random.choice(messages)
139+
embed.add_field(name="The winner drawn at random is", value=f"This [video]({winner.jump_url}) of {winner.author.mention}!", inline=True)
140+
141+
match = re.search(YOUTUBE_REGEX, winner.content)
113142
code = await send_video_to_endpoint(video_url=match.group(0))
114-
if code == SUCCESS_CODE:
115-
embed.add_field(name="Website state", value=f"{await self.bot.fetch_application_emoji(IDs.customEmojis.CONNECTE)} Video sent to [repuls.io]({Links.REPULS_GAME})!")
116-
else:
117-
embed.add_field(name="Website state", value=f"{DefaultEmojis.WARN} Video failed to send to repuls.io ({code} error)!")
118143

119-
await video_channel.send(embed=embed)
120-
else:
121-
await video_channel.send(f"""
122-
I couldn't find any videos to display on the game's homepage 🫤...
123-
**Become a <@&{IDs.serverRoles.YOUTUBER}> by meeting [the following requirements](https://discord.com/channels/603655329120518223/733177088961544202/1389263121591570496), and post your first videos!** 🚀""")
144+
log_channel = self.bot.get_channel(IDs.serverChannel.LOG)
145+
if log_channel:
146+
if code == SUCCESS_CODE:
147+
status = f"{DefaultEmojis.CHECK} Video sent to repuls.io!"
148+
else:
149+
status = f"{DefaultEmojis.WARN} Video failed to send to repuls.io ({code} error)"
150+
await log_channel.send(f"**Website state** : {status}", silent=True)
151+
152+
await video_channel.send(embed=embed)
124153

125154
# ---------------------------------- command
126155
@commands.hybrid_command(name="video_leaderboard", description="Show the most voted YouTube videos")
@@ -145,7 +174,7 @@ async def video_leaderboard(self, ctx: commands.Context, hours: int = VOTE_HOURS
145174

146175
msg = await video_channel.fetch_message(message.id)
147176
for reaction in msg.reactions:
148-
if str(reaction.emoji) == DefaultEmojis.CHECK:
177+
if str(reaction.emoji) == REACTION:
149178
if ENV == ENV_DEV_MODE:
150179
video_votes.append((reaction.count, msg))
151180
elif reaction.count > 1: # prod mode

src/constants.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class ServerChannelID:
2424
RULES = 1389989335318794420 if ENV == ENV_DEV_MODE else 758364818348048444
2525
STATUS = 1370716216863227924 if ENV == ENV_DEV_MODE else 849711794032214087
2626
VIDEO = 1370706473155563581 if ENV == ENV_DEV_MODE else 800108276004028446
27+
TICKETS_CATEGORY = 1390286889830842470 if ENV == ENV_DEV_MODE else 1398622102713667605
2728

2829
class ServerRoleID: # "<@&role_id>"
2930
YOUTUBER = 1381223948854759494 if ENV == ENV_DEV_MODE else 781295509331116054

src/utils.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,8 @@ async def send_hidden_message(ctx: commands.Context, text: str):
1919
await ctx.send(text, delete_after=10.0)
2020

2121
def hoursdelta(hours) -> datetime:
22-
return discord.utils.utcnow() - timedelta(hours=hours)
22+
return discord.utils.utcnow() - timedelta(hours=hours)
23+
24+
def nl(string: str) -> str:
25+
""" returns a string without line breaks """
26+
return string.replace('\n', ' ').strip()

0 commit comments

Comments
 (0)