From 005bbfd1e589578835f4fb88935f70ac4424d330 Mon Sep 17 00:00:00 2001 From: Kavin <20838718+FireMasterK@users.noreply.github.com> Date: Wed, 16 Nov 2022 23:04:45 +0000 Subject: [PATCH] Implement channel data federation. --- .../server/handlers/ChannelHandlers.java | 32 ++++------- .../me/kavin/piped/utils/ChannelHelpers.java | 57 +++++++++++++++++++ .../kavin/piped/utils/matrix/SyncRunner.java | 17 +++++- .../obj/federation/FederatedChannelInfo.java | 33 ++++++++++- 4 files changed, 113 insertions(+), 26 deletions(-) create mode 100644 src/main/java/me/kavin/piped/utils/ChannelHelpers.java diff --git a/src/main/java/me/kavin/piped/server/handlers/ChannelHandlers.java b/src/main/java/me/kavin/piped/server/handlers/ChannelHandlers.java index efbfb3d..4f9903c 100644 --- a/src/main/java/me/kavin/piped/server/handlers/ChannelHandlers.java +++ b/src/main/java/me/kavin/piped/server/handlers/ChannelHandlers.java @@ -7,6 +7,7 @@ import me.kavin.piped.ipfs.IPFS; import me.kavin.piped.utils.*; import me.kavin.piped.utils.obj.*; import me.kavin.piped.utils.obj.db.Video; +import me.kavin.piped.utils.obj.federation.FederatedChannelInfo; import me.kavin.piped.utils.obj.federation.FederatedVideoInfo; import me.kavin.piped.utils.resp.InvalidRequestResponse; import org.apache.commons.lang3.StringUtils; @@ -57,6 +58,14 @@ public class ChannelHandlers { } })); + Multithreading.runAsync(() -> { + try { + MatrixHelper.sendEvent("video.piped.channel.info", new FederatedChannelInfo(info.getId(), info.getName(), info.getAvatarUrl(), info.isVerified())); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + Multithreading.runAsync(() -> { var channel = DatabaseHelper.getChannelFromId(info.getId()); @@ -65,28 +74,7 @@ public class ChannelHandlers { if (channel != null) { - boolean modified = false; - - if (channel.isVerified() != info.isVerified()) { - channel.setVerified(info.isVerified()); - modified = true; - } - - if (!channel.getUploaderAvatar().equals(info.getAvatarUrl())) { - channel.setUploaderAvatar(info.getAvatarUrl()); - modified = true; - } - - if (!channel.getUploader().equals(info.getName())) { - channel.setUploader(info.getName()); - modified = true; - } - - if (modified) { - var tr = s.beginTransaction(); - s.update(channel); - tr.commit(); - } + ChannelHelpers.updateChannel(s, channel, info.getName(), info.getAvatarUrl(), info.isVerified()); Set ids = info.getRelatedItems() .stream() diff --git a/src/main/java/me/kavin/piped/utils/ChannelHelpers.java b/src/main/java/me/kavin/piped/utils/ChannelHelpers.java new file mode 100644 index 0000000..b70569a --- /dev/null +++ b/src/main/java/me/kavin/piped/utils/ChannelHelpers.java @@ -0,0 +1,57 @@ +package me.kavin.piped.utils; + +import me.kavin.piped.consts.Constants; +import me.kavin.piped.utils.obj.db.Channel; +import okhttp3.Request; +import org.hibernate.StatelessSession; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; + +public class ChannelHelpers { + + public static void updateChannel(StatelessSession s, Channel channel, String name, String avatarUrl, boolean uploaderVerified) { + + boolean changed = false; + + if (name != null && !name.equals(channel.getUploader())) { + channel.setUploader(name); + changed = true; + } + + if (avatarUrl != null && !avatarUrl.equals(channel.getUploaderAvatar())) { + + URL url; + try { + url = new URL(avatarUrl); + if (!url.getHost().endsWith(".ggpht.com")) + return; + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + + try (var resp = Constants.h2client.newCall(new Request.Builder().url(url).head().build()).execute()) { + + if (resp.isSuccessful()) + channel.setUploaderAvatar(avatarUrl); + + changed = true; + } catch (IOException e) { + return; + } + } + + if (uploaderVerified != channel.isVerified()) { + channel.setVerified(uploaderVerified); + changed = true; + } + + if (changed) { + var tr = s.beginTransaction(); + s.update(channel); + tr.commit(); + } + } + +} diff --git a/src/main/java/me/kavin/piped/utils/matrix/SyncRunner.java b/src/main/java/me/kavin/piped/utils/matrix/SyncRunner.java index d34ab4b..755050f 100644 --- a/src/main/java/me/kavin/piped/utils/matrix/SyncRunner.java +++ b/src/main/java/me/kavin/piped/utils/matrix/SyncRunner.java @@ -134,9 +134,11 @@ public class SyncRunner implements Runnable { continue; } + var content = event.at("/content/content"); + switch (type) { case "video.piped.stream.info" -> { - FederatedVideoInfo info = mapper.treeToValue(event.at("/content/content"), FederatedVideoInfo.class); + FederatedVideoInfo info = mapper.treeToValue(content, FederatedVideoInfo.class); Multithreading.runAsync(() -> { try (StatelessSession s = DatabaseSessionFactory.createStatelessSession()) { var video = DatabaseHelper.getVideoFromId(s, info.getVideoId()); @@ -153,8 +155,17 @@ public class SyncRunner implements Runnable { }); } case "video.piped.channel.info" -> { - FederatedChannelInfo info = mapper.treeToValue(event.at("/content/content"), FederatedChannelInfo.class); - // TODO: Handle and send channel updates + FederatedChannelInfo info = mapper.treeToValue(content, FederatedChannelInfo.class); + Multithreading.runAsync(() -> { + try (StatelessSession s = DatabaseSessionFactory.createStatelessSession()) { + var channel = DatabaseHelper.getChannelFromId(s, info.getId()); + if (channel != null) + ChannelHelpers.updateChannel(s, channel, + info.getName(), + info.getUploaderUrl(), + info.isVerified()); + } + }); } default -> System.err.println("Unknown event type: " + type); } diff --git a/src/main/java/me/kavin/piped/utils/obj/federation/FederatedChannelInfo.java b/src/main/java/me/kavin/piped/utils/obj/federation/FederatedChannelInfo.java index c354018..0712aab 100644 --- a/src/main/java/me/kavin/piped/utils/obj/federation/FederatedChannelInfo.java +++ b/src/main/java/me/kavin/piped/utils/obj/federation/FederatedChannelInfo.java @@ -2,6 +2,37 @@ package me.kavin.piped.utils.obj.federation; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -@JsonIgnoreProperties +@JsonIgnoreProperties(ignoreUnknown = true) public class FederatedChannelInfo { + + private String id; + private String name; + private String uploaderUrl; + private boolean verified; + + public FederatedChannelInfo() { + } + + public FederatedChannelInfo(String id, String name, String uploaderUrl, boolean verified) { + this.id = id; + this.name = name; + this.uploaderUrl = uploaderUrl; + this.verified = verified; + } + + public String getId() { + return id; + } + + public String getName() { + return name; + } + + public String getUploaderUrl() { + return uploaderUrl; + } + + public boolean isVerified() { + return verified; + } }