-
Notifications
You must be signed in to change notification settings - Fork 111
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add an event inverter utility class #113
base: master
Are you sure you want to change the base?
Conversation
Looked through every method. Added all methods that can logically be inverted. Implemented some inversions as samples
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Few notes. But also a general question: What use cases for this do you have in mind?
commons/src/main/java/com/jagrosh/jdautilities/commons/utils/InverseAction.java
Outdated
Show resolved
Hide resolved
public static RoleAction of(RoleDeleteEvent event) | ||
{ | ||
return event.getRole().createCopy(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be made more clear which events are only "partially" reversible or if those should even be included. That is, you can create a copy of that role, but everything that still uses the old id is still broken and the members that used to have it don't have it anymore.
Same for e.g. voice channel delete.
I see it being mentioned in the summary javadoc, but it's still somewhat confusing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wouldn't include inverse actions for deleting/removing events since you can't invert it fully.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe it could be part of the documentation. I agree, my contract promises full reversion, but since that's not a promise I can keep while still wanting to implement the inverses to deletions, I can simply include it in the contract that most inversions regarding the removal of an entity will only be partial, and all immutable state from the original entity cannot possibly be copied
This seems like an interesting - but niche - concept. I've taken a preliminary glance at what you have so far, and I not a huge fan of having a bunch of static methods, all with different return types. Ideally, something like this would be possible: List<Event> someEventsToRevert; // accumulates somehow
List<RestAction> restActionsToCall;
for(Event e: someEventsToRevert)
restActionsToCall.add(someInvertMethodOrEnclosingClass(e)); which would also mean that giving this system any generic event would return either a RestAction, or possibly throw an exception if there's no suitable inversion to the event. |
commons/src/main/java/com/jagrosh/jdautilities/commons/utils/InverseAction.java
Outdated
Show resolved
Hide resolved
@jagrosh Thank you for the view, and I understand your concern in terms of the differing return types thing, however, the documentation states that my class guarantees a return type of |
@JohnnyJayJay Thanks for the view, and about your question with use cases, I believed it would be nice to wrap the instances where you want to "undo" certain actions. Like jagrosh pointed out, it's niche, I agree, but in the instances where it can come in handy, it's nice and neat. For example, say you want to prevent a moderator from being able to create a TextChannel under certain circumstances: you'd check the context, and |
Just a question @HydroPage90 but isn't the inverse of a guild ban being unbanned instead of banning with a 0 day prune again? |
@Sanduhr32 Dang it |
I also have a concern about having a different overload for each specific event that could be simplified to an XYZGenericXYZEvent, where you internally check for the specific type of event then handle it in an according way, because they are very likely to have the same return value. Edit: English |
I agree, it could have been done this way, but I believe separating into the overloads allows me to document the subtle logical differences between the inversions. Their return type may be the same, but the logic behind returning the objects is not |
The way you have it set up, you can't actually pass a GenericEvent into the system at all, nor different kinds of events in the same loop; there's no exception because it wouldn't even compile. |
Understood. So you would like for me to wrap the API I've made by only making generic event methods publicly accessible, and using my |
For clarification, a bot that attempts to invert every event should be no more complicated than this: class MyListener implements EventListener {
@Override
onEvent(GenericEvent event) {
try {
RestAction action = someInversionMethod(event);
action.queue();
} catch (PermissionException e) {
System.out.println("Insufficient perms to invert " + event);
} catch (InversionException e) {
System.out.println("Cannot invert " + event);
}
}
} |
It's fine if the methods provide more type information than necessary, but they should respect inheritance when possible |
@jagrosh Got it, I will get to work on generifying. What do you think we should do about methods that violate my contract slightly? (Like a Role deletion being unable to be undone due to copying it giving it a new ID, and the people who had it losing the Role) |
I'm not sure how I could go about making this work. I don't want to make an public static RestAction<?> of(GenericEvent event)
{
try
{
Class<? extends GenericEvent> eventClass = event.getClass();
if (invertableEvents.contains(eventClass))
{
return (RestAction<?>) InverseAction.class.getMethod("inverse", eventClass)
.invoke(InverseAction.class, event);
}
}
catch (ReflectiveOperationException e)
{
throw new InversionException("No available inversion for event " + event, e);
}
return null;
} Is this a good start? Or should I stick with making a tower of |
I think I'll stick with the |
Alright. Made a singular public delegator method, renamed |
Wrong tag, smh. Sorry, whoever that is, lmao |
Pull Request
Pull Request Checklist
or merged features/bug fixes.
Pull Request Information
commons
module of the JDA-Utilities library.______
.Description
I have begun implementing a utility class I have, as of now, named
InverseAction
. I have explained the granular details in the class' javadoc, but I can summarize here. This util class' contract promises to return aRestAction<?>
that will effectively wrap the "undoing" of a given input event type. This is to clean the instances where you want to detect an event, and revert its effects if the context around the event meets certain causes, etc.Again, this will only be implemented for events in which it makes sense to fully be able to "undo" an action that was done.
The removal of a voice channel can be undone effectively; however, the removal of a text channel cannot, and will not be included.
I have sifted carefully through every event in JDA (There are some I'm still not sure of, I believe) to include only the events that can be logically reverted by the bot.
I have included the implementation of a couple of the first methods in the class so you can get a full understanding of what I mean. I hope you will accept my feature proposal