From e1498ec80eb35d497d223e6da1894d9d5d6ae648 Mon Sep 17 00:00:00 2001
From: Koen <koen@pop-os.localdomain>
Date: Tue, 15 Aug 2023 12:43:34 +0200
Subject: [PATCH] Implemented multi-claim endpoints.

---
 .idea/androidTestResultsUserPreferences.xml   |  14 ++
 .../core/GenerateTestProfileTests.kt          |   5 +-
 .../java/com/futo/polycentric/core/Claims.kt  | 129 ++++++++++--------
 .../java/com/futo/polycentric/core/Utility.kt |  15 --
 .../futo/polycentric/protos/protocol.proto    |  15 +-
 5 files changed, 90 insertions(+), 88 deletions(-)

diff --git a/.idea/androidTestResultsUserPreferences.xml b/.idea/androidTestResultsUserPreferences.xml
index 52521d3..bc5f7b4 100644
--- a/.idea/androidTestResultsUserPreferences.xml
+++ b/.idea/androidTestResultsUserPreferences.xml
@@ -44,6 +44,20 @@
             </AndroidTestResultsTableState>
           </value>
         </entry>
+        <entry key="-1620268414">
+          <value>
+            <AndroidTestResultsTableState>
+              <option name="preferredColumnWidths">
+                <map>
+                  <entry key="29211JEGR13699" value="120" />
+                  <entry key="Duration" value="90" />
+                  <entry key="Google&#10; Pixel 6a" value="120" />
+                  <entry key="Tests" value="360" />
+                </map>
+              </option>
+            </AndroidTestResultsTableState>
+          </value>
+        </entry>
         <entry key="-1603504896">
           <value>
             <AndroidTestResultsTableState>
diff --git a/app/src/androidTest/java/com/futo/polycentric/core/GenerateTestProfileTests.kt b/app/src/androidTest/java/com/futo/polycentric/core/GenerateTestProfileTests.kt
index 360616d..c154f47 100644
--- a/app/src/androidTest/java/com/futo/polycentric/core/GenerateTestProfileTests.kt
+++ b/app/src/androidTest/java/com/futo/polycentric/core/GenerateTestProfileTests.kt
@@ -16,8 +16,7 @@ class GenerateTestProfileTests {
         s1p1.setStore("https://amazon.com/")
 
         val claims = listOf(
-            s1p1.claim(Claims.youtube("@koen-futo")),
-            s1p1.claim(Claims.youtube("UCR7KMD7jkSefYYWgSwNPEBA")),
+            s1p1.claim(Claims.youtube("UCR7KMD7jkSefYYWgSwNPEBA", "@koen-futo")),
             s1p1.claim(Claims.rumble("c/c-3366838")),
             s1p1.claim(Claims.rumble("user/koenfuto")),
             s1p1.claim(Claims.bitcoin("bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh"))
@@ -68,7 +67,7 @@ class GenerateTestProfileTests {
 
         val claims = listOf(
             s1p1.claim(Claims.hackerNews("eron_wolf")),
-            s1p1.claim(Claims.youtube("@FUTOTECH")),
+            s1p1.claim(Claims.youtube("UCR7KMD7jkSefYYWgSwNPEBA", "@koen-futo")),
             s1p1.claim(Claims.odysee("@FUTO")),
             s1p1.claim(Claims.rumble("rossmanngroup")),
             s1p1.claim(Claims.discord("thekinocorner")),
diff --git a/app/src/main/java/com/futo/polycentric/core/Claims.kt b/app/src/main/java/com/futo/polycentric/core/Claims.kt
index b44ba9e..17c9242 100644
--- a/app/src/main/java/com/futo/polycentric/core/Claims.kt
+++ b/app/src/main/java/com/futo/polycentric/core/Claims.kt
@@ -4,148 +4,157 @@ import userpackage.Protocol
 
 class Claims {
     companion object {
+        //TODO: Update once claim types have been known
         fun hackerNews(id: String): Protocol.Claim {
-            return claim(ClaimType.HACKER_NEWS.value, id)
+            return claim(ClaimType.HACKER_NEWS.value, mapOf(0L to id))
         }
 
-        fun youtube(id: String): Protocol.Claim {
-            return claim(ClaimType.YOUTUBE.value, id)
+        fun youtube(internalId: String, handle: String): Protocol.Claim {
+            return claim(ClaimType.YOUTUBE.value, mapOf(
+                0L to internalId,
+                1L to handle
+            ))
         }
 
         fun odysee(id: String): Protocol.Claim {
-            return claim(ClaimType.ODYSEE.value, id)
+            return claim(ClaimType.ODYSEE.value, mapOf(0L to id))
         }
 
         fun rumble(id: String): Protocol.Claim {
-            return claim(ClaimType.RUMBLE.value, id)
+            return claim(ClaimType.RUMBLE.value, mapOf(0L to id))
         }
 
         fun discord(id: String): Protocol.Claim {
-            return claim(ClaimType.DISCORD.value, id)
+            return claim(ClaimType.DISCORD.value, mapOf(0L to id))
         }
 
         fun instagram(id: String): Protocol.Claim {
-            return claim(ClaimType.INSTAGRAM.value, id)
+            return claim(ClaimType.INSTAGRAM.value, mapOf(0L to id))
         }
 
         fun twitch(id: String): Protocol.Claim {
-            return claim(ClaimType.TWITCH.value, id)
+            return claim(ClaimType.TWITCH.value, mapOf(0L to id))
         }
 
         fun url(url: String): Protocol.Claim {
-            return claim(ClaimType.URL.value, url);
+            return claim(ClaimType.URL.value, mapOf(0L to url));
         }
 
         fun bitcoin(id: String): Protocol.Claim {
-            return claim(ClaimType.BITCOIN.value, id);
+            return claim(ClaimType.BITCOIN.value, mapOf(0L to id));
         }
 
         fun twitter(id: String): Protocol.Claim {
-            return claim(ClaimType.TWITTER.value, id)
+            return claim(ClaimType.TWITTER.value, mapOf(0L to id))
         }
 
         fun generic(id: String): Protocol.Claim {
-            return claim(ClaimType.GENERIC.value, id)
+            return claim(ClaimType.GENERIC.value, mapOf(0L to id))
         }
 
         fun github(id: String): Protocol.Claim {
-            return claim(ClaimType.GITHUB.value, id)
+            return claim(ClaimType.GITHUB.value, mapOf(0L to id))
         }
 
         fun minds(id: String): Protocol.Claim {
-            return claim(ClaimType.MINDS.value, id)
+            return claim(ClaimType.MINDS.value, mapOf(0L to id))
         }
 
         fun patreon(id: String): Protocol.Claim {
-            return claim(ClaimType.PATREON.value, id)
+            return claim(ClaimType.PATREON.value, mapOf(0L to id))
         }
 
         fun substack(id: String): Protocol.Claim {
-            return claim(ClaimType.SUBSTACK.value, id)
+            return claim(ClaimType.SUBSTACK.value, mapOf(0L to id))
         }
 
         fun website(id: String): Protocol.Claim {
-            return claim(ClaimType.WEBSITE.value, id)
+            return claim(ClaimType.WEBSITE.value, mapOf(0L to id))
         }
 
         fun kick(id: String): Protocol.Claim {
-            return claim(ClaimType.KICK.value, id)
+            return claim(ClaimType.KICK.value, mapOf(0L to id))
         }
 
         fun soundcloud(id: String): Protocol.Claim {
-            return claim(ClaimType.SOUNDCLOUD.value, id)
+            return claim(ClaimType.SOUNDCLOUD.value, mapOf(0L to id))
         }
 
         fun vimeo(id: String): Protocol.Claim {
-            return claim(ClaimType.VIMEO.value, id)
+            return claim(ClaimType.VIMEO.value, mapOf(0L to id))
         }
 
         fun nebula(id: String): Protocol.Claim {
-            return claim(ClaimType.NEBULA.value, id)
+            return claim(ClaimType.NEBULA.value, mapOf(0L to id))
         }
 
         fun occupation(id: String): Protocol.Claim {
-            return claim(ClaimType.OCCUPATION.value, id)
+            return claim(ClaimType.OCCUPATION.value, mapOf(0L to id))
         }
 
         fun skill(id: String): Protocol.Claim {
-            return claim(ClaimType.SKILL.value, id)
+            return claim(ClaimType.SKILL.value, mapOf(0L to id))
         }
 
         fun spotify(id: String): Protocol.Claim {
-            return claim(ClaimType.SPOTIFY.value, id)
+            return claim(ClaimType.SPOTIFY.value, mapOf(0L to id))
         }
 
         fun spreadshop(id: String): Protocol.Claim {
-            return claim(ClaimType.SPREADSHOP.value, id)
+            return claim(ClaimType.SPREADSHOP.value, mapOf(0L to id))
         }
 
         fun polycentric(id: String): Protocol.Claim {
-            return claim(ClaimType.POLYCENTRIC.value, id)
+            return claim(ClaimType.POLYCENTRIC.value, mapOf(0L to id))
         }
 
-        fun claim(claimType: Long, id: String?): Protocol.Claim{
+        fun claim(type: Long, fields: Map<Long, String>): Protocol.Claim{
             return Protocol.Claim.newBuilder()
-                .setClaimType(claimType)
-                .setClaim(Protocol.ClaimIdentifier.newBuilder()
-                    .setIdentifier(id)
-                    .build()
-                    .toByteString())
+                .setClaimType(type)
+                .addAllClaimFields(fields.map {
+                    Protocol.ClaimFieldEntry.newBuilder()
+                        .setKey(it.key)
+                        .setValue(it.value)
+                        .build()
+                })
                 .build()
         }
     }
 }
 
-fun Protocol.Claim.toUrl(): String? {
+fun Protocol.Claim.toUrl(key: Long): String? {
     return when (claimType) {
-        ClaimType.HACKER_NEWS.value -> "https://news.ycombinator.com/user?id=${Protocol.ClaimIdentifier.parseFrom(claim).identifier}"
+        ClaimType.HACKER_NEWS.value -> if (key == 0L) claimFieldsList.firstOrNull { it.key == 0L }?.let { "https://news.ycombinator.com/user?id=${it.value}" } else null
         ClaimType.YOUTUBE.value -> {
-            val c = Protocol.ClaimIdentifier.parseFrom(claim).identifier
-            if (c.startsWith('@')) "https://www.youtube.com/$c" else "https://www.youtube.com/channel/$c"
-        }
-        ClaimType.ODYSEE.value -> "https://odysee.com/${Protocol.ClaimIdentifier.parseFrom(claim).identifier}"
-        ClaimType.RUMBLE.value -> "https://rumble.com/${Protocol.ClaimIdentifier.parseFrom(claim).identifier}"
-        ClaimType.TWITTER.value -> "https://twitter.com/${Protocol.ClaimIdentifier.parseFrom(claim).identifier}"
-        ClaimType.BITCOIN.value -> "bitcoin:${Protocol.ClaimIdentifier.parseFrom(claim).identifier}"
-        ClaimType.GENERIC.value -> Protocol.ClaimIdentifier.parseFrom(claim).identifier
-        ClaimType.DISCORD.value -> "https://discordapp.com/users/${Protocol.ClaimIdentifier.parseFrom(claim).identifier}"
-        ClaimType.INSTAGRAM.value -> "https://instagram.com/${Protocol.ClaimIdentifier.parseFrom(claim).identifier}"
-        ClaimType.GITHUB.value -> "https://github.com/${Protocol.ClaimIdentifier.parseFrom(claim).identifier}"
-        ClaimType.MINDS.value -> "https://www.minds.com/${Protocol.ClaimIdentifier.parseFrom(claim).identifier}"
-        ClaimType.PATREON.value -> "https://www.patreon.com/${Protocol.ClaimIdentifier.parseFrom(claim).identifier}"
-        ClaimType.SUBSTACK.value -> "https://${Protocol.ClaimIdentifier.parseFrom(claim).identifier}.substack.com" //TODO: Check this
-        ClaimType.TWITCH.value -> "https://www.twitch.tv/${Protocol.ClaimIdentifier.parseFrom(claim).identifier}"
-        ClaimType.WEBSITE.value -> Protocol.ClaimIdentifier.parseFrom(claim).identifier
-        ClaimType.KICK.value -> "https://www.kickstarter.com/profile/${Protocol.ClaimIdentifier.parseFrom(claim).identifier}" //TODO: Check this
-        ClaimType.SOUNDCLOUD.value -> "https://soundcloud.com/${Protocol.ClaimIdentifier.parseFrom(claim).identifier}"
-        ClaimType.VIMEO.value -> "https://vimeo.com/${Protocol.ClaimIdentifier.parseFrom(claim).identifier}"
-        ClaimType.NEBULA.value -> "https://nebula.tv/${Protocol.ClaimIdentifier.parseFrom(claim).identifier}"
-        ClaimType.URL.value -> Protocol.ClaimIdentifier.parseFrom(claim).identifier
-        ClaimType.OCCUPATION.value -> null
-        ClaimType.SKILL.value -> null
-        ClaimType.SPOTIFY.value -> "https://open.spotify.com/user/${Protocol.ClaimIdentifier.parseFrom(claim).identifier}"
-        ClaimType.SPREADSHOP.value -> "https://${Protocol.ClaimIdentifier.parseFrom(claim).identifier}.spreadshop.com" //TODO: Check this
-        ClaimType.POLYCENTRIC.value -> "polycentric://${Protocol.ClaimIdentifier.parseFrom(claim).identifier}"
+            when (key) {
+                0L -> claimFieldsList.firstOrNull { it.key == 0L }?.let { "https://www.youtube.com/channel/${it.value}" }
+                1L -> claimFieldsList.firstOrNull { it.key == 1L }?.let { "https://www.youtube.com/${it.value}" }
+                else -> null
+            }
+        }
+        ClaimType.ODYSEE.value -> if (key == 0L) claimFieldsList.firstOrNull { it.key == 0L }?.let { "https://odysee.com/${it.value}" } else null
+        ClaimType.RUMBLE.value -> if (key == 0L) claimFieldsList.firstOrNull { it.key == 0L }?.let { "https://rumble.com/${it.value}" } else null
+        ClaimType.TWITTER.value -> if (key == 0L) claimFieldsList.firstOrNull { it.key == 0L }?.let { "https://twitter.com/${it.value}" } else null
+        ClaimType.BITCOIN.value -> if (key == 0L) claimFieldsList.firstOrNull { it.key == 0L }?.let { "bitcoin:${it.value}" } else null
+        ClaimType.GENERIC.value -> null //TODO: Implement?
+        ClaimType.DISCORD.value -> if (key == 0L) claimFieldsList.firstOrNull { it.key == 0L }?.let { "https://discordapp.com/users/${it.value}" } else null
+        ClaimType.INSTAGRAM.value -> if (key == 0L) claimFieldsList.firstOrNull { it.key == 0L }?.let { "https://instagram.com/${it.value}" } else null
+        ClaimType.GITHUB.value -> if (key == 0L) claimFieldsList.firstOrNull { it.key == 0L }?.let { "https://github.com/${it.value}" } else null
+        ClaimType.MINDS.value -> if (key == 0L) claimFieldsList.firstOrNull { it.key == 0L }?.let { "https://www.minds.com/${it.value}" } else null
+        ClaimType.PATREON.value -> if (key == 0L) claimFieldsList.firstOrNull { it.key == 0L }?.let { "https://www.patreon.com/${it.value}" } else null
+        ClaimType.SUBSTACK.value -> if (key == 0L) claimFieldsList.firstOrNull { it.key == 0L }?.let { "https://${it.value}.substack.com" } else null //TODO: Check this
+        ClaimType.TWITCH.value -> if (key == 0L) claimFieldsList.firstOrNull { it.key == 0L }?.let { "https://www.twitch.tv/${it.value}" } else null
+        ClaimType.WEBSITE.value -> null //TODO: Implement?
+        ClaimType.KICK.value -> if (key == 0L) claimFieldsList.firstOrNull { it.key == 0L }?.let { "https://www.kickstarter.com/profile/${it.value}" } else null //TODO: Check this
+        ClaimType.SOUNDCLOUD.value -> if (key == 0L) claimFieldsList.firstOrNull { it.key == 0L }?.let { "https://soundcloud.com/${it.value}" } else null
+        ClaimType.VIMEO.value -> if (key == 0L) claimFieldsList.firstOrNull { it.key == 0L }?.let { "https://vimeo.com/${it.value}" } else null
+        ClaimType.NEBULA.value -> if (key == 0L) claimFieldsList.firstOrNull { it.key == 0L }?.let { "https://nebula.tv/${it.value}" } else null
+        ClaimType.URL.value -> null //TODO: Implement?
+        ClaimType.OCCUPATION.value -> null //TODO: Implement?
+        ClaimType.SKILL.value -> null //TODO: Implement?
+        ClaimType.SPOTIFY.value -> if (key == 0L) claimFieldsList.firstOrNull { it.key == 0L }?.let { "https://open.spotify.com/user/${it.value}" } else null
+        ClaimType.SPREADSHOP.value -> if (key == 0L) claimFieldsList.firstOrNull { it.key == 0L }?.let { "https://${it.value}.spreadshop.com" } else null //TODO: Check this
+        ClaimType.POLYCENTRIC.value -> if (key == 0L) claimFieldsList.firstOrNull { it.key == 0L }?.let { "polycentric://${it.value}" } else null
         else -> null
     }
 }
diff --git a/app/src/main/java/com/futo/polycentric/core/Utility.kt b/app/src/main/java/com/futo/polycentric/core/Utility.kt
index 7874816..b65e956 100644
--- a/app/src/main/java/com/futo/polycentric/core/Utility.kt
+++ b/app/src/main/java/com/futo/polycentric/core/Utility.kt
@@ -49,21 +49,6 @@ fun List<SignedEvent>.getValidClaims(): List<OwnedClaim> {
     return validClaims;
 }
 
-fun List<SignedEvent>.getValidClaim(c: Claim): OwnedClaim? {
-    for (e in this) {
-        if (e.event.contentType == ContentType.CLAIM.value) {
-            val claim = getClaimIfValid(e)
-            if (claim != null) {
-                if (claim.claim.claimType == c.claimType && claim.claim.claim == c.claim) {
-                    return claim;
-                }
-            }
-        }
-    }
-
-    return null;
-}
-
 fun List<SignedEvent>.getClaimIfValid(claimEvent: SignedEvent): OwnedClaim? {
     if (claimEvent.event.contentType != ContentType.CLAIM.value) {
         return null
diff --git a/app/src/main/proto/com/futo/polycentric/protos/protocol.proto b/app/src/main/proto/com/futo/polycentric/protos/protocol.proto
index 709436d..542c07d 100644
--- a/app/src/main/proto/com/futo/polycentric/protos/protocol.proto
+++ b/app/src/main/proto/com/futo/polycentric/protos/protocol.proto
@@ -150,18 +150,13 @@ message Post {
 }
 
 message Claim {
-    uint64 claim_type = 1;
-    bytes  claim      = 2;
+             uint64          claim_type   = 1;
+    repeated ClaimFieldEntry claim_fields = 2;
 }
 
-message ClaimIdentifier {
-    string identifier = 1;
-}
-
-message ClaimOccupation {
-    string organization = 1;
-    string role         = 2;
-    string location     = 3;
+message ClaimFieldEntry {
+    uint64 key   = 1;
+    string value = 2;
 }
 
 message Vouch {}
-- 
GitLab