Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>net.pcsx2</groupId>
<artifactId>HifumiBot</artifactId>
<version>4.9.2</version>
<version>4.10.0</version>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
Expand Down
95 changes: 48 additions & 47 deletions src/main/java/net/pcsx2/hifumi/database/Database.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,20 @@
import java.util.List;
import java.util.Optional;

import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.Message.Attachment;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.entities.automod.AutoModResponse;
import net.dv8tion.jda.api.events.automod.AutoModExecutionEvent;
import net.dv8tion.jda.api.events.guild.GuildBanEvent;
import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent;
import net.dv8tion.jda.api.events.guild.member.GuildMemberRemoveEvent;
import net.dv8tion.jda.api.events.message.MessageBulkDeleteEvent;
import net.dv8tion.jda.api.events.message.MessageDeleteEvent;
import net.dv8tion.jda.api.events.message.MessageUpdateEvent;
import net.dv8tion.jda.api.events.user.update.UserUpdateGlobalNameEvent;
import net.dv8tion.jda.api.events.user.update.UserUpdateNameEvent;
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.pcsx2.hifumi.HifumiBot;
import net.pcsx2.hifumi.charting.AutomodChartData;
import net.pcsx2.hifumi.charting.MemberChartData;
Expand All @@ -27,27 +41,12 @@
import net.pcsx2.hifumi.util.TimeUtils;
import net.pcsx2.hifumi.util.UserUtils;

import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.Message.Attachment;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.entities.automod.AutoModResponse;
import net.dv8tion.jda.api.events.automod.AutoModExecutionEvent;
import net.dv8tion.jda.api.events.guild.GuildBanEvent;
import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent;
import net.dv8tion.jda.api.events.guild.member.GuildMemberRemoveEvent;
import net.dv8tion.jda.api.events.message.MessageBulkDeleteEvent;
import net.dv8tion.jda.api.events.message.MessageDeleteEvent;
import net.dv8tion.jda.api.events.message.MessageUpdateEvent;
import net.dv8tion.jda.api.events.user.update.UserUpdateGlobalNameEvent;
import net.dv8tion.jda.api.events.user.update.UserUpdateNameEvent;
import net.dv8tion.jda.api.interactions.commands.OptionMapping;

public class Database {

/**
* Store user, channel, message, attachment, and event records
*/
public static void insertMessage(Message message, boolean skipEvent) {
public static void insertMessage(Message message) {
Connection conn = HifumiBot.getSelf().getSQLite().getConnection();

try {
Expand Down Expand Up @@ -75,7 +74,7 @@ INSERT INTO channel (discord_id, name)
// Check if the referenced message exists in the database; if not, try to add it first.
if (message.getReferencedMessage() != null) {
if (Database.getLatestMessage(message.getReferencedMessage().getIdLong()) == null) {
Database.insertMessage(message.getReferencedMessage(), skipEvent);
Database.insertMessage(message.getReferencedMessage());
}
}

Expand All @@ -99,7 +98,7 @@ INSERT INTO message (message_id, fk_channel, jump_link, fk_reply_to_message, tim
insertMessage.executeUpdate();
insertMessage.close();

if (!skipEvent) {
if (!HifumiBot.getSelf().getPermissionManager().hasMessageLogBypass(message)) {
PreparedStatement insertEvent = conn.prepareStatement("""
INSERT INTO message_event (fk_user, fk_message, timestamp, action, content)
VALUES (?, ?, ?, ?, ?);
Expand Down Expand Up @@ -308,39 +307,41 @@ INSERT INTO message (message_id, fk_channel, fk_user)
insertMessage.executeUpdate();
insertMessage.close();

List<Attachment> attachments = event.getMessage().getAttachments();
if (!HifumiBot.getSelf().getPermissionManager().hasMessageLogBypass(event.getMessage())) {
List<Attachment> attachments = event.getMessage().getAttachments();

if (!attachments.isEmpty()) {
PreparedStatement insertAttachment = conn.prepareStatement("""
INSERT INTO message_attachment (discord_id, timestamp, fk_message, content_type, proxy_url)
VALUES (?, ?, ?, ?, ?)
ON CONFLICT (discord_id) DO NOTHING;
""");
if (!attachments.isEmpty()) {
PreparedStatement insertAttachment = conn.prepareStatement("""
INSERT INTO message_attachment (discord_id, timestamp, fk_message, content_type, proxy_url)
VALUES (?, ?, ?, ?, ?)
ON CONFLICT (discord_id) DO NOTHING;
""");

for (Attachment attachment : attachments) {
insertAttachment.setLong(1, attachment.getIdLong());
insertAttachment.setLong(2, attachment.getTimeCreated().toEpochSecond());
insertAttachment.setLong(3, event.getMessageIdLong());
insertAttachment.setString(4, attachment.getContentType());
insertAttachment.setString(5, attachment.getProxyUrl());
insertAttachment.addBatch();
for (Attachment attachment : attachments) {
insertAttachment.setLong(1, attachment.getIdLong());
insertAttachment.setLong(2, attachment.getTimeCreated().toEpochSecond());
insertAttachment.setLong(3, event.getMessageIdLong());
insertAttachment.setString(4, attachment.getContentType());
insertAttachment.setString(5, attachment.getProxyUrl());
insertAttachment.addBatch();
}

insertAttachment.executeBatch();
insertAttachment.close();
}

insertAttachment.executeBatch();
insertAttachment.close();
}

PreparedStatement insertEvent = conn.prepareStatement("""
INSERT INTO message_event (fk_user, fk_message, timestamp, action, content)
VALUES (?, ?, ?, ?, ?);
""");
insertEvent.setLong(1, event.getAuthor().getIdLong());
insertEvent.setLong(2, event.getMessageIdLong());
insertEvent.setLong(3, (event.getMessage().getTimeEdited() != null ? event.getMessage().getTimeEdited() : event.getMessage().getTimeCreated()).toEpochSecond());
insertEvent.setString(4, "edit");
insertEvent.setString(5, event.getMessage().getContentRaw());
insertEvent.executeUpdate();
insertEvent.close();
PreparedStatement insertEvent = conn.prepareStatement("""
INSERT INTO message_event (fk_user, fk_message, timestamp, action, content)
VALUES (?, ?, ?, ?, ?);
""");
insertEvent.setLong(1, event.getAuthor().getIdLong());
insertEvent.setLong(2, event.getMessageIdLong());
insertEvent.setLong(3, (event.getMessage().getTimeEdited() != null ? event.getMessage().getTimeEdited() : event.getMessage().getTimeCreated()).toEpochSecond());
insertEvent.setString(4, "edit");
insertEvent.setString(5, event.getMessage().getContentRaw());
insertEvent.executeUpdate();
insertEvent.close();
}
} catch (SQLException e) {
Messaging.logException("Database", "insertMessageUpdateEvent", e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,9 @@ public void onMessageReceived(MessageReceivedEvent event) {

// Make note of Hifumi's identity and elevation for later
String hifumiUserId = HifumiBot.getSelf().getJDA().getSelfUser().getId();
boolean hasElevatedPerms = HifumiBot.getSelf().getPermissionManager().hasPermission(PermissionLevel.ADMIN, event.getMember());
boolean isHifumi = event.getAuthor().getId().equals(hifumiUserId);

// Store all messages, exclude highly privileged users
boolean skipEvent = hasElevatedPerms || isHifumi;
Database.insertMessage(event.getMessage(), skipEvent);
Database.insertMessage(event.getMessage());

// If the sender was the bot, do not process any further.
if (isHifumi) {
Expand Down
55 changes: 53 additions & 2 deletions src/main/java/net/pcsx2/hifumi/permissions/PermissionManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,17 @@
package net.pcsx2.hifumi.permissions;

import java.util.ArrayList;
import java.util.Optional;

import net.pcsx2.hifumi.HifumiBot;

import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.Role;
import net.pcsx2.hifumi.HifumiBot;
import net.pcsx2.hifumi.util.MemberUtils;

public class PermissionManager {

private String superuserId;

public PermissionManager(String superuserId) {
Expand All @@ -51,6 +55,8 @@ public PermissionManager(String superuserId) {
if (HifumiBot.getSelf().getConfig().permissions.superAdminRoleIds == null) {
HifumiBot.getSelf().getConfig().permissions.superAdminRoleIds = new ArrayList<String>();
}

this.validateRoles();
}

public boolean hasPermission(PermissionLevel permissionLevel, Member member) {
Expand Down Expand Up @@ -93,4 +99,49 @@ public boolean hasPermission(PermissionLevel permissionLevel, Member member) {
return false;
}
}

public boolean hasPermission(PermissionRole permissionRole, Member member) {
if (permissionRole != null && member != null) {
for (Role role : member.getRoles()) {
if (role.getName().equals(permissionRole.toString())) {
return true;
}
}
}

return false;
}

/**
* Convenience method to simplify checking if a message's author has the log bypass permission.
* @param message - The message to check
* @return True if the author has the bypass permission, false otherwise.
*/
public boolean hasMessageLogBypass(Message message) {
if (message.getChannelType().isGuild()) {
Guild server = message.getGuild();
Optional<Member> memberOpt = MemberUtils.getOrRetrieveMember(server, message.getAuthor().getId());

if (memberOpt.isPresent()) {
return this.hasPermission(PermissionRole.MESSAGE_LOG_BYPASS_ROLE, memberOpt.get());
}
}

return false;
}

private void validateRoles(String... roleNames) {
for (Guild server : HifumiBot.getSelf().getJDA().getGuilds()) {
for (PermissionRole permissionRole : PermissionRole.values()) {
String roleName = permissionRole.toString();

if (server.getRolesByName(roleName, true).isEmpty()) {
server.createRole()
.setName(roleName)
.setMentionable(false)
.queue();
}
}
}
}
}
23 changes: 23 additions & 0 deletions src/main/java/net/pcsx2/hifumi/permissions/PermissionRole.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package net.pcsx2.hifumi.permissions;

public enum PermissionRole
{
MESSAGE_LOG_BYPASS_ROLE("Hifumi MLB");

private String roleName;

private PermissionRole(String roleName)
{
this.roleName = roleName;
}

/**
* Resolve this enum to the display name of the Role it is supposed to represent.
* @return String value of the role's display name
*/
@Override
public String toString()
{
return this.roleName;
}
}