a tool for shared writing and social publishing
at test/unknown-marks 242 lines 6.7 kB view raw
1"use server"; 2import { TID } from "@atproto/common"; 3import { 4 AtpBaseClient, 5 PubLeafletPublication, 6 PubLeafletThemeColor, 7} from "lexicons/api"; 8import { createOauthClient } from "src/atproto-oauth"; 9import { getIdentityData } from "actions/getIdentityData"; 10import { supabaseServerClient } from "supabase/serverClient"; 11import { Json } from "supabase/database.types"; 12import { AtUri } from "@atproto/syntax"; 13import { redirect } from "next/navigation"; 14import { $Typed } from "@atproto/api"; 15import { ids } from "lexicons/api/lexicons"; 16 17export async function updatePublication({ 18 uri, 19 name, 20 description, 21 iconFile, 22 preferences, 23}: { 24 uri: string; 25 name: string; 26 description: string; 27 iconFile: File | null; 28 preferences?: Omit<PubLeafletPublication.Preferences, "$type">; 29}) { 30 const oauthClient = await createOauthClient(); 31 let identity = await getIdentityData(); 32 if (!identity || !identity.atp_did) return; 33 34 let credentialSession = await oauthClient.restore(identity.atp_did); 35 let agent = new AtpBaseClient( 36 credentialSession.fetchHandler.bind(credentialSession), 37 ); 38 let { data: existingPub } = await supabaseServerClient 39 .from("publications") 40 .select("*") 41 .eq("uri", uri) 42 .single(); 43 if (!existingPub || existingPub.identity_did !== identity.atp_did) return; 44 let aturi = new AtUri(existingPub.uri); 45 46 let record: PubLeafletPublication.Record = { 47 $type: "pub.leaflet.publication", 48 ...(existingPub.record as object), 49 name, 50 }; 51 if (preferences) { 52 record.preferences = preferences; 53 } 54 55 if (description !== undefined) { 56 record.description = description; 57 } 58 59 // Upload the icon if provided How do I tell if there isn't a new one? 60 if (iconFile && iconFile.size > 0) { 61 const buffer = await iconFile.arrayBuffer(); 62 const uploadResult = await agent.com.atproto.repo.uploadBlob( 63 new Uint8Array(buffer), 64 { encoding: iconFile.type }, 65 ); 66 67 if (uploadResult.data.blob) { 68 record.icon = uploadResult.data.blob; 69 } 70 } 71 72 let result = await agent.com.atproto.repo.putRecord({ 73 repo: credentialSession.did!, 74 rkey: aturi.rkey, 75 record, 76 collection: record.$type, 77 validate: false, 78 }); 79 80 //optimistically write to our db! 81 let { data: publication, error } = await supabaseServerClient 82 .from("publications") 83 .update({ 84 name: record.name, 85 record: record as Json, 86 }) 87 .eq("uri", uri) 88 .select() 89 .single(); 90 if (name !== existingPub.name) 91 return redirect( 92 `/lish/${aturi.host}/${encodeURIComponent(name)}/dashboard`, 93 ); 94 95 return { success: true, publication }; 96} 97 98export async function updatePublicationBasePath({ 99 uri, 100 base_path, 101}: { 102 uri: string; 103 base_path: string; 104}) { 105 const oauthClient = await createOauthClient(); 106 let identity = await getIdentityData(); 107 if (!identity || !identity.atp_did) return; 108 109 let credentialSession = await oauthClient.restore(identity.atp_did); 110 let agent = new AtpBaseClient( 111 credentialSession.fetchHandler.bind(credentialSession), 112 ); 113 let { data: existingPub } = await supabaseServerClient 114 .from("publications") 115 .select("*") 116 .eq("uri", uri) 117 .single(); 118 if (!existingPub || existingPub.identity_did !== identity.atp_did) return; 119 let aturi = new AtUri(existingPub.uri); 120 121 let record: PubLeafletPublication.Record = { 122 ...(existingPub.record as PubLeafletPublication.Record), 123 base_path, 124 }; 125 126 let result = await agent.com.atproto.repo.putRecord({ 127 repo: credentialSession.did!, 128 rkey: aturi.rkey, 129 record, 130 collection: record.$type, 131 validate: false, 132 }); 133 134 //optimistically write to our db! 135 let { data: publication, error } = await supabaseServerClient 136 .from("publications") 137 .update({ 138 name: record.name, 139 record: record as Json, 140 }) 141 .eq("uri", uri) 142 .select() 143 .single(); 144 return { success: true, publication }; 145} 146 147type Color = 148 | $Typed<PubLeafletThemeColor.Rgb, "pub.leaflet.theme.color#rgb"> 149 | $Typed<PubLeafletThemeColor.Rgba, "pub.leaflet.theme.color#rgba">; 150export async function updatePublicationTheme({ 151 uri, 152 theme, 153}: { 154 uri: string; 155 theme: { 156 backgroundImage?: File | null; 157 backgroundRepeat?: number | null; 158 backgroundColor: Color; 159 primary: Color; 160 pageBackground: Color; 161 showPageBackground: boolean; 162 accentBackground: Color; 163 accentText: Color; 164 }; 165}) { 166 const oauthClient = await createOauthClient(); 167 let identity = await getIdentityData(); 168 if (!identity || !identity.atp_did) return; 169 170 let credentialSession = await oauthClient.restore(identity.atp_did); 171 let agent = new AtpBaseClient( 172 credentialSession.fetchHandler.bind(credentialSession), 173 ); 174 let { data: existingPub } = await supabaseServerClient 175 .from("publications") 176 .select("*") 177 .eq("uri", uri) 178 .single(); 179 if (!existingPub || existingPub.identity_did !== identity.atp_did) return; 180 let aturi = new AtUri(existingPub.uri); 181 182 let oldRecord = existingPub.record as PubLeafletPublication.Record; 183 let record: PubLeafletPublication.Record = { 184 ...oldRecord, 185 $type: "pub.leaflet.publication", 186 theme: { 187 backgroundImage: theme.backgroundImage 188 ? { 189 $type: "pub.leaflet.theme.backgroundImage", 190 image: ( 191 await agent.com.atproto.repo.uploadBlob( 192 new Uint8Array(await theme.backgroundImage.arrayBuffer()), 193 { encoding: theme.backgroundImage.type }, 194 ) 195 )?.data.blob, 196 width: theme.backgroundRepeat || undefined, 197 repeat: !!theme.backgroundRepeat, 198 } 199 : theme.backgroundImage === null 200 ? undefined 201 : oldRecord.theme?.backgroundImage, 202 backgroundColor: theme.backgroundColor 203 ? { 204 ...theme.backgroundColor, 205 } 206 : undefined, 207 primary: { 208 ...theme.primary, 209 }, 210 pageBackground: { 211 ...theme.pageBackground, 212 }, 213 showPageBackground: theme.showPageBackground, 214 accentBackground: { 215 ...theme.accentBackground, 216 }, 217 accentText: { 218 ...theme.accentText, 219 }, 220 }, 221 }; 222 223 let result = await agent.com.atproto.repo.putRecord({ 224 repo: credentialSession.did!, 225 rkey: aturi.rkey, 226 record, 227 collection: record.$type, 228 validate: false, 229 }); 230 231 //optimistically write to our db! 232 let { data: publication, error } = await supabaseServerClient 233 .from("publications") 234 .update({ 235 name: record.name, 236 record: record as Json, 237 }) 238 .eq("uri", uri) 239 .select() 240 .single(); 241 return { success: true, publication }; 242}