Skip to content

Commit

Permalink
✨ Block social media accounts closes #79
Browse files Browse the repository at this point in the history
Signed-off-by: Marcus Fihlon <[email protected]>
  • Loading branch information
McPringle committed Apr 9, 2024
1 parent e4778da commit c193a1a
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 37 deletions.
41 changes: 37 additions & 4 deletions src/main/java/swiss/fihlon/apus/service/SocialService.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ public final class SocialService {
private final boolean filterSensitive;
private final List<String> filterWords;
private final Set<String> manuallyHiddenId = new HashSet<>();
private final Set<String> manuallyHiddenProfile = new HashSet<>();
private List<Message> messages = List.of();

public SocialService(@NotNull final TaskScheduler taskScheduler,
Expand All @@ -64,6 +65,7 @@ public SocialService(@NotNull final TaskScheduler taskScheduler,
.map(filterWord -> filterWord.toLowerCase(DEFAULT_LOCALE).trim())
.toList();
loadHiddenMessageIds();
loadHiddenProfiles();
updateMessages();
updateScheduler = taskScheduler.scheduleAtFixedRate(this::updateMessages, UPDATE_FREQUENCY);
}
Expand All @@ -76,6 +78,7 @@ public void stopUpdateScheduler() {
private void updateMessages() {
final var newMessages = mastodonAPI.getMessages().stream()
.filter(message -> !manuallyHiddenId.contains(message.id()))
.filter(message -> !manuallyHiddenProfile.contains(message.profile()))
.filter(message -> !filterSensitive || !message.isSensitive())
.filter(message -> !filterReplies || !message.isReply())
.filter(this::checkWordFilter)
Expand Down Expand Up @@ -113,7 +116,15 @@ public void hideMessage(@NotNull final Message message) {
saveHiddenMessageIds();
}

private Path getHiddenMessagesFilePath() {
public void hideProfile(@NotNull final Message message) {
LOGGER.warn("Hide profile (id={}, profile={}, author={})",
message.id(), message.profile(), message.author());
messages.remove(message);
manuallyHiddenProfile.add(message.profile());
saveHiddenProfiles();
}

private Path getConfigDir() {
final Path configDir = Path.of(System.getProperty("user.home"), ".apus");
if (!configDir.toFile().exists()) {
try {
Expand All @@ -122,20 +133,29 @@ private Path getHiddenMessagesFilePath() {
LOGGER.error("Unable to create configuration directory {}: {}", configDir, e.getMessage());
}
}
return configDir.resolve("hiddenMessageIds");
return configDir;
}

private void saveHiddenMessageIds() {
final var filePath = getHiddenMessagesFilePath();
final var filePath = getConfigDir().resolve("hiddenMessageIds");
try {
Files.writeString(filePath, String.join("\n", manuallyHiddenId));
} catch (final IOException e) {
LOGGER.error("Unable to save hidden message IDs to file '{}': {}", filePath, e.getMessage());
}
}

private void saveHiddenProfiles() {
final var filePath = getConfigDir().resolve("hiddenProfiles");
try {
Files.writeString(filePath, String.join("\n", manuallyHiddenProfile));
} catch (final IOException e) {
LOGGER.error("Unable to save hidden profiles to file '{}': {}", filePath, e.getMessage());
}
}

private void loadHiddenMessageIds() {
final var filePath = getHiddenMessagesFilePath();
final var filePath = getConfigDir().resolve("hiddenMessageIds");
if (filePath.toFile().exists()) {
try {
manuallyHiddenId.addAll(Files.readAllLines(filePath));
Expand All @@ -146,4 +166,17 @@ private void loadHiddenMessageIds() {
LOGGER.info("No previously saved hidden message IDs found.");
}
}

private void loadHiddenProfiles() {
final var filePath = getConfigDir().resolve("hiddenProfiles");
if (filePath.toFile().exists()) {
try {
manuallyHiddenProfile.addAll(Files.readAllLines(filePath));
} catch (IOException e) {
LOGGER.error("Unable to load hidden profiles from file '{}': {}", filePath, e.getMessage());
}
} else {
LOGGER.info("No previously saved hidden profiles found.");
}
}
}
82 changes: 71 additions & 11 deletions src/main/java/swiss/fihlon/apus/ui/view/MessageView.java
Original file line number Diff line number Diff line change
Expand Up @@ -78,22 +78,23 @@ private Component createAvatarComponent(@NotNull final Message message) {
final var avatar = new Avatar(message.author(), message.avatar());
if (!configuration.getAdmin().password().isBlank()) {
final var menu = new ContextMenu();
menu.addItem(getTranslation("social.message.contextmenu.hide"), event -> confirmHideMessage(message));
menu.addItem(getTranslation("social.message.contextmenu.hide.message"), event -> confirmHideMessage(message));
menu.addItem(getTranslation("social.message.contextmenu.hide.profile"), event -> confirmHideProfile(message));
menu.setTarget(avatar);
}
return avatar;
}

private void confirmHideMessage(@NotNull final Message message) {
final var dialog = new ConfirmDialog();
dialog.setHeader(getTranslation("social.message.dialog.hide.confirm.title"));
dialog.setText(getTranslation("social.message.dialog.hide.confirm.text", message.author(), message.date()));
dialog.setHeader(getTranslation("social.message.dialog.hide.message.confirm.title"));
dialog.setText(getTranslation("social.message.dialog.hide.message.confirm.text", message.author(), message.date()));
dialog.setCloseOnEsc(true);

dialog.setCancelable(true);
dialog.setCancelButton(getTranslation("social.message.dialog.hide.confirm.cancel"), event -> dialog.close());
dialog.setCancelButton(getTranslation("social.message.dialog.hide.message.confirm.cancel"), event -> dialog.close());

dialog.setConfirmText(getTranslation("social.message.dialog.hide.confirm.button"));
dialog.setConfirmText(getTranslation("social.message.dialog.hide.message.confirm.button"));
dialog.addConfirmListener(event -> {
dialog.close();
authorizeHideMessage(message);
Expand All @@ -104,24 +105,24 @@ private void confirmHideMessage(@NotNull final Message message) {

private void authorizeHideMessage(@NotNull final Message message) {
final Dialog dialog = new Dialog();
dialog.setHeaderTitle(getTranslation("social.message.dialog.hide.authorize.title"));
dialog.setHeaderTitle(getTranslation("social.message.dialog.hide.message.authorize.title"));
dialog.setCloseOnEsc(true);
dialog.setCloseOnOutsideClick(true);

final PasswordField passwordField = new PasswordField();
passwordField.setPlaceholder(getTranslation("social.message.dialog.hide.authorize.password"));
passwordField.setPlaceholder(getTranslation("social.message.dialog.hide.message.authorize.password"));
passwordField.setRequired(true);
passwordField.setValueChangeMode(ValueChangeMode.EAGER);

final Button hideButton = new Button(getTranslation("social.message.dialog.hide.authorize.button"), event -> {
final Button hideButton = new Button(getTranslation("social.message.dialog.hide.message.authorize.button"), event -> {
dialog.close();
hideMessage(message, passwordField.getValue());
});
hideButton.setEnabled(false);
hideButton.setDisableOnClick(true);
hideButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY);

final Button cancelButton = new Button(getTranslation("social.message.dialog.hide.authorize.cancel"), event -> dialog.close());
final Button cancelButton = new Button(getTranslation("social.message.dialog.hide.message.authorize.cancel"), event -> dialog.close());
cancelButton.setDisableOnClick(true);
cancelButton.addThemeVariants(ButtonVariant.LUMO_TERTIARY);
dialog.getFooter().add(hideButton, cancelButton);
Expand All @@ -137,9 +138,68 @@ private void hideMessage(@NotNull final Message message, @NotNull final String p
if (password.equals(configuration.getAdmin().password())) {
socialService.hideMessage(message);
removeFromParent();
Notification.show(getTranslation("social.message.notification.hide.success", message.author()));
Notification.show(getTranslation("social.message.notification.hide.message.success", message.author()));
} else {
Notification.show(getTranslation("social.message.notification.hide.rejected"));
Notification.show(getTranslation("social.message.notification.hide.message.rejected"));
}
}

private void confirmHideProfile(@NotNull final Message message) {
final var dialog = new ConfirmDialog();
dialog.setHeader(getTranslation("social.message.dialog.hide.profile.confirm.title"));
dialog.setText(getTranslation("social.message.dialog.hide.profile.confirm.text", message.profile(), message.author()));
dialog.setCloseOnEsc(true);

dialog.setCancelable(true);
dialog.setCancelButton(getTranslation("social.message.dialog.hide.profile.confirm.cancel"), event -> dialog.close());

dialog.setConfirmText(getTranslation("social.message.dialog.hide.profile.confirm.button"));
dialog.addConfirmListener(event -> {
dialog.close();
authorizeHideProfile(message);
});

dialog.open();
}

private void authorizeHideProfile(@NotNull final Message message) {
final Dialog dialog = new Dialog();
dialog.setHeaderTitle(getTranslation("social.message.dialog.hide.profile.authorize.title"));
dialog.setCloseOnEsc(true);
dialog.setCloseOnOutsideClick(true);

final PasswordField passwordField = new PasswordField();
passwordField.setPlaceholder(getTranslation("social.message.dialog.hide.profile.authorize.password"));
passwordField.setRequired(true);
passwordField.setValueChangeMode(ValueChangeMode.EAGER);

final Button hideButton = new Button(getTranslation("social.message.dialog.hide.profile.authorize.button"), event -> {
dialog.close();
hideProfile(message, passwordField.getValue());
});
hideButton.setEnabled(false);
hideButton.setDisableOnClick(true);
hideButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY);

final Button cancelButton = new Button(getTranslation("social.message.dialog.hide.profile.authorize.cancel"), event -> dialog.close());
cancelButton.setDisableOnClick(true);
cancelButton.addThemeVariants(ButtonVariant.LUMO_TERTIARY);
dialog.getFooter().add(hideButton, cancelButton);

passwordField.addKeyDownListener(event -> hideButton.setEnabled(!passwordField.isEmpty()));
dialog.add(passwordField);

dialog.open();
passwordField.focus();
}

private void hideProfile(@NotNull final Message message, @NotNull final String password) {
if (password.equals(configuration.getAdmin().password())) {
socialService.hideProfile(message);
removeFromParent();
Notification.show(getTranslation("social.message.notification.hide.profile.success", message.profile(), message.author()));
} else {
Notification.show(getTranslation("social.message.notification.hide.profile.rejected"));
}
}

Expand Down
33 changes: 22 additions & 11 deletions src/main/resources/vaadin-i18n/translations.properties
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,25 @@ conference.room.empty=closed
conference.session.countdown.plural=ends in {0} minutes
conference.session.countdown.singular=ends in {0} minute
social.heading=Posts with #{0} on Mastodon
social.message.contextmenu.hide="Hide this message"
social.message.dialog.hide.authorize.button=Hide
social.message.dialog.hide.authorize.cancel=Cancel
social.message.dialog.hide.authorize.password=Password
social.message.dialog.hide.authorize.title=Authorize
social.message.dialog.hide.confirm.button=Hide
social.message.dialog.hide.confirm.cancel=Cancel
social.message.dialog.hide.confirm.text=Do you really want to hide this message from {0} posted at {1}?
social.message.dialog.hide.confirm.title=Confirm
social.message.notification.hide.rejected=You are not authorized to hide messages!
social.message.notification.hide.success=This message from {0} was hidden as requested.
social.message.contextmenu.hide.message=Hide this message
social.message.dialog.hide.message.authorize.button=Hide
social.message.dialog.hide.message.authorize.cancel=Cancel
social.message.dialog.hide.message.authorize.password=Password
social.message.dialog.hide.message.authorize.title=Authorize
social.message.dialog.hide.message.confirm.button=Hide
social.message.dialog.hide.message.confirm.cancel=Cancel
social.message.dialog.hide.message.confirm.text=Do you really want to hide this message from {0} posted at {1}?
social.message.dialog.hide.message.confirm.title=Confirm
social.message.notification.hide.message.rejected=You are not authorized to hide messages!
social.message.notification.hide.message.success=This message from {0} was hidden as requested.
social.message.contextmenu.hide.profile=Hide this profile
social.message.dialog.hide.profile.authorize.button=Hide
social.message.dialog.hide.profile.authorize.cancel=Cancel
social.message.dialog.hide.profile.authorize.password=Password
social.message.dialog.hide.profile.authorize.title=Authorize
social.message.dialog.hide.profile.confirm.button=Hide
social.message.dialog.hide.profile.confirm.cancel=Cancel
social.message.dialog.hide.profile.confirm.text=Do you really want to hide the profile {0} ({1})?
social.message.dialog.hide.profile.confirm.title=Confirm
social.message.notification.hide.profile.rejected=You are not authorized to hide profiles!
social.message.notification.hide.profile.success=The profile {0} ({1}) was hidden as requested.
33 changes: 22 additions & 11 deletions src/main/resources/vaadin-i18n/translations_de.properties
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,25 @@ conference.room.empty=geschlossen
conference.session.countdown.plural=endet in {0} Minuten
conference.session.countdown.singular=endet in {0} Minute
social.heading=Schreibe einen Beitrag mit #{0} auf Mastodon
social.message.contextmenu.hide=Diesen Beitrag ausblenden
social.message.dialog.hide.authorize.button=Ausblenden
social.message.dialog.hide.authorize.cancel=Abbrechen
social.message.dialog.hide.authorize.password=Passwort
social.message.dialog.hide.authorize.title=Authorisieren
social.message.dialog.hide.confirm.button=Ausblenden
social.message.dialog.hide.confirm.cancel=Abbrechen
social.message.dialog.hide.confirm.text=Möchtest du diesen am {1} geschriebenen Beitrag von {0} ausblenden?
social.message.dialog.hide.confirm.title=Bestätigen
social.message.notification.hide.rejected=Du bist nicht authorisiert, Beiträge auszublenden!
social.message.notification.hide.success=Dieser Beitrag von {0} wurde wie gewünscht ausgeblendet.
social.message.contextmenu.hide.message=Diesen Beitrag ausblenden
social.message.dialog.hide.message.authorize.button=Ausblenden
social.message.dialog.hide.message.authorize.cancel=Abbrechen
social.message.dialog.hide.message.authorize.password=Passwort
social.message.dialog.hide.message.authorize.title=Authorisieren
social.message.dialog.hide.message.confirm.button=Ausblenden
social.message.dialog.hide.message.confirm.cancel=Abbrechen
social.message.dialog.hide.message.confirm.text=Möchtest du diesen am {1} geschriebenen Beitrag von {0} ausblenden?
social.message.dialog.hide.message.confirm.title=Bestätigen
social.message.notification.hide.message.rejected=Du bist nicht authorisiert, Beiträge auszublenden!
social.message.notification.hide.message.success=Dieser Beitrag von {0} wurde wie gewünscht ausgeblendet.
social.message.contextmenu.hide.profile=Dieses Profil ausblenden
social.message.dialog.hide.profile.authorize.button=Ausblenden
social.message.dialog.hide.profile.authorize.cancel=Abbrechen
social.message.dialog.hide.profile.authorize.password=Passwort
social.message.dialog.hide.profile.authorize.title=Authorisieren
social.message.dialog.hide.profile.confirm.button=Ausblenden
social.message.dialog.hide.profile.confirm.cancel=Abbrechen
social.message.dialog.hide.profile.confirm.text=Möchtest du das Profil {1} von {0} ausblenden?
social.message.dialog.hide.profile.confirm.title=Bestätigen
social.message.notification.hide.profile.rejected=Du bist nicht authorisiert, Profile auszublenden!
social.message.notification.hide.profile.success=Das Profile {0} von {1} wurde wie gewünscht ausgeblendet.

0 comments on commit c193a1a

Please sign in to comment.