Skip to content

Commit

Permalink
Adds initial mastodon status stream support
Browse files Browse the repository at this point in the history
- listen to status updates containing defined hash tags
- listen to status messages of defined users

Signed-off-by: Patrick Reinhart <[email protected]>
  • Loading branch information
reinhapa committed Apr 4, 2023
1 parent ad47099 commit 69d3897
Show file tree
Hide file tree
Showing 17 changed files with 1,574 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2022 TweetWallFX
* Copyright (c) 2018-2023 TweetWallFX
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
Expand Down Expand Up @@ -139,6 +139,7 @@ public final URLContent getCachedOrLoad(final String urlString) {
* @param contentConsumer the Consumer processing the content
*/
public final void getCachedOrLoad(final String urlString, final Consumer<URLContent> contentConsumer) {
Objects.requireNonNull(urlString, "urlString must not be null");
Objects.requireNonNull(contentConsumer, "contentConsumer must not be null");

contentLoader.execute(() -> {
Expand All @@ -152,6 +153,7 @@ public final void getCachedOrLoad(final String urlString, final Consumer<URLCont
}

private URLContent getCachedOrLoadSync(final String urlString) throws IOException {
Objects.requireNonNull(urlString, "urlString must not be null");
URLContent urlc = urlContentCache.get(urlString);

if (null == urlc) {
Expand Down
6 changes: 5 additions & 1 deletion tweet-impl-mastodon4j/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@
dependencies {
api project(':tweetwallfx-tweet-api')

// implementation 'org.mastodon4j:mastodon4j-core:1.0.0-SNAPSHOT'
implementation 'org.eclipse:yasson:3.0.0'
implementation 'org.jsoup:jsoup:1.15.4'
implementation 'org.mastodon4j:mastodon4j-core:0.9.0'
implementation 'org.slf4j:slf4j-api:2.0.4'

testImplementation 'org.simplify4u:slf4j2-mock:2.3.0'
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2023 TweetWallFX
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.tweetwallfx.tweet.impl.mastodon4j;

import org.mastodon4j.core.api.entities.Account;
import org.mastodon4j.core.api.entities.Status;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class AccountPredicate implements Predicate<Status> {
private static final Logger LOGGER = LoggerFactory.getLogger(AccountPredicate.class);
private final Set<String> userList;

public AccountPredicate(List<String> userList) {
this.userList = Objects.requireNonNull(userList, "userList must not be null").stream()
.map(user -> user.substring(1))
.collect(Collectors.toCollection(() -> new TreeSet<>(String::compareToIgnoreCase)));
}

@Override
public boolean test(Status status) {
final String username = status.account().username();
if (userList.contains(username)) {
return true;
} else {
LOGGER.debug("No matching users {} for account {}", userList, username);
return false;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2023 TweetWallFX
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.tweetwallfx.tweet.impl.mastodon4j;

import jakarta.json.bind.Jsonb;
import jakarta.json.bind.JsonbBuilder;
import org.mastodon4j.core.api.entities.Event;
import org.mastodon4j.core.api.entities.Status;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Predicate;

public class EventStatusConsumer implements Consumer<Event> {
private static final Logger LOGGER = LoggerFactory.getLogger(EventStatusConsumer.class);
private final Consumer<Status> statusConsumer;
private final Predicate<Status> statusPredicate;

EventStatusConsumer(Consumer<Status> statusConsumer) {
this(statusConsumer, status -> true);
}

EventStatusConsumer(Consumer<Status> statusConsumer, Predicate<Status> statusPredicate) {
this.statusConsumer = Objects.requireNonNull(statusConsumer, "statusConsumer must not be null");
this.statusPredicate = Objects.requireNonNull(statusPredicate, "statusPredicate must not be null");
}

private void notifyStatusPayload(String payload) {
LOGGER.debug("Processing payload:\n{}", payload);
try (Jsonb jsonb = JsonbBuilder.create()) {
final Status status = jsonb.fromJson(payload, Status.class);
if (statusPredicate.test(status)) {
statusConsumer.accept(status);
} else {
LOGGER.debug("Status {} not matching criteria", status.id());
}
} catch (Exception e) {
LOGGER.error("Failed to notify status", e);
}
}

@Override
public void accept(Event event) {
switch (event.event()) {
case "update", "status.update" -> notifyStatusPayload(event.payload());
default -> LOGGER.debug("Ignoring event:\n{}", event);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2023 TweetWallFX
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.tweetwallfx.tweet.impl.mastodon4j;

import org.mastodon4j.core.api.entities.Account;
import org.mastodon4j.core.api.entities.Field;
import org.tweetwallfx.tweet.api.User;

import java.util.Objects;

public class MastodonAccount implements User {
private final Account account;

public MastodonAccount(Account account) {
this.account = account;
}

@Override
public String getBiggerProfileImageUrl() {
return getProfileImageUrl();
}

@Override
public long getId() {
return Long.parseLong(account.id());
}

@Override
public String getLang() {
return "not-supported";
}

@Override
public String getName() {
return account.username();
}

@Override
public String getProfileImageUrl() {
return account.avatar();
}

@Override
public String getScreenName() {
return account.display_name();
}

@Override
public int getFollowersCount() {
return account.followers_count();
}

@Override
public boolean isVerified() {
return account.fields().stream().map(Field::verified_at).anyMatch(Objects::nonNull);
}
}
Loading

0 comments on commit 69d3897

Please sign in to comment.