1"use strict";(globalThis.webpackChunkbsky_docs||=[]).push([[4836],{7741(e,t,r){r.r(t),r.d(t,{assets:()=>d,contentTitle:()=>c,default:()=>p,frontMatter:()=>a,metadata:()=>n,toc:()=>u});const n=JSON.parse('{"id":"bluesky-api/like-repost","title":"Liking and reposting","description":"Liking and reposting posts are core Bluesky actions. A like or repost is itself a record in the user\'s repository \u2014 many SDKs provide dedicated helpers for creating and removing them.","source":"@site/docs/bluesky-api/like-repost.mdx","sourceDirName":"bluesky-api","slug":"/bluesky-api/like-repost","permalink":"/docs/bluesky-api/like-repost","draft":false,"unlisted":false,"editUrl":"https://github.com/bluesky-social/bps-website/tree/main/docs/bluesky-api/like-repost.mdx","tags":[],"version":"current","sidebarPosition":4,"frontMatter":{"sidebar_position":4},"sidebar":"tutorialSidebar","previous":{"title":"Viewing threads","permalink":"/docs/bluesky-api/viewing-threads"},"next":{"title":"Profiles","permalink":"/docs/bluesky-api/profiles"}}');var s=r(4848),i=r(8453),l=r(5645),o=r(9608);const a={sidebar_position:4},c="Liking and reposting",d={},u=[{value:"Liking a post",id:"liking-a-post",level:2},{value:"Unliking a post",id:"unliking-a-post",level:2},{value:"Reposting a post",id:"reposting-a-post",level:2},{value:"Un-reposting a post",id:"un-reposting-a-post",level:2},{value:"Quote reposting",id:"quote-reposting",level:2}];function h(e){const t={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",header:"header",hr:"hr",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.header,{children:(0,s.jsx)(t.h1,{id:"liking-and-reposting",children:"Liking and reposting"})}),"\n",(0,s.jsx)(t.p,{children:"Liking and reposting posts are core Bluesky actions. A like or repost is itself a record in the user's repository \u2014 many SDKs provide dedicated helpers for creating and removing them."}),"\n",(0,s.jsx)(t.h2,{id:"liking-a-post",children:"Liking a post"}),"\n",(0,s.jsx)(t.p,{children:"Liking a post requires the post's URI and its CID."}),"\n",(0,s.jsx)(t.p,{children:"The URI indicates the repository DID, collection, and record key. The CID is the hash of the record itself."}),"\n",(0,s.jsxs)(l.A,{groupId:"sdk",children:[(0,s.jsx)(o.A,{value:"ts",label:"TypeScript",children:(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-typescript",metastring:'title="like"',children:" import { like } from '@bsky/sdk'\n\n const { uri: likeUri } = await client.call(like, { uri, cid })\n"})})}),(0,s.jsx)(o.A,{value:"python",label:"Python",children:(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-python",metastring:'title="client.like"',children:" uri = client.like(uri=uri, cid=cid).uri\n"})})}),(0,s.jsxs)(o.A,{value:"go",label:"Go",children:[(0,s.jsxs)(t.p,{children:["The Go SDK has no dedicated helper; create an ",(0,s.jsx)(t.code,{children:"app.bsky.feed.like"})," record pointing at the post:"]}),(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-go",children:'like := &appbsky.FeedLike{\n CreatedAt: time.Now().UTC().Format(time.RFC3339),\n Subject: &comatproto.RepoStrongRef{Uri: uri, Cid: cid},\n}\nresp, _ := comatproto.RepoCreateRecord(ctx, client, &comatproto.RepoCreateRecord_Input{\n Repo: client.AccountDID.String(),\n Collection: "app.bsky.feed.like",\n Record: &lexutil.LexiconTypeDecoder{Val: like},\n})\n'})})]})]}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{children:"Parameter"}),(0,s.jsx)(t.th,{children:"Type"}),(0,s.jsx)(t.th,{children:"Description"}),(0,s.jsx)(t.th,{children:"Required"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:(0,s.jsx)(t.code,{children:"uri"})}),(0,s.jsx)(t.td,{children:(0,s.jsx)(t.code,{children:"string"})}),(0,s.jsx)(t.td,{children:"The URI of the post"}),(0,s.jsx)(t.td,{children:"Yes"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:(0,s.jsx)(t.code,{children:"cid"})}),(0,s.jsx)(t.td,{children:(0,s.jsx)(t.code,{children:"string"})}),(0,s.jsx)(t.td,{children:"The CID of the post"}),(0,s.jsx)(t.td,{children:"Yes"})]})]})]}),"\n",(0,s.jsx)(t.h2,{id:"unliking-a-post",children:"Unliking a post"}),"\n",(0,s.jsx)(t.p,{children:"Unliking a post requires only the post's URI, which refers to its record.\nIn the case of a Like, unliking the post means deleting the Like record."}),"\n",(0,s.jsxs)(l.A,{groupId:"sdk",children:[(0,s.jsx)(o.A,{value:"ts",label:"TypeScript",children:(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-typescript",metastring:'title="deleteLike"',children:" import { deleteLike }
1 from '@bsky/sdk'\n\n await client.call(deleteLike, likeUri)\n"})})}),(0,s.jsx)(o.A,{value:"python",label:"Python",children:(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-python",metastring:'title="client.delete_like"',children:" client.delete_like(uri)\n"})})}),(0,s.jsxs)(o.A,{value:"go",label:"Go",children:[(0,s.jsx)(t.p,{children:"Delete the like record. Its rkey is the last segment of the URI returned when you created it:"}),(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-go",children:'import "strings"\n\nrkey := uri[strings.LastIndex(uri, "/")+1:]\ncomatproto.RepoDeleteRecord(ctx, client, &comatproto.RepoDeleteRecord_Input{\n Repo: client.AccountDID.String(),\n Collection: "app.bsky.feed.like",\n Rkey: rkey,\n})\n'})})]})]}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{children:"Parameter"}),(0,s.jsx)(t.th,{children:"Type"}),(0,s.jsx)(t.th,{children:"Description"}),(0,s.jsx)(t.th,{children:"Required"})]})}),(0,s.jsx)(t.tbody,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:(0,s.jsx)(t.code,{children:"uri"})}),(0,s.jsx)(t.td,{children:(0,s.jsx)(t.code,{children:"string"})}),(0,s.jsx)(t.td,{children:"The URI of the like record to delete"}),(0,s.jsx)(t.td,{children:"Yes"})]})})]}),"\n",(0,s.jsx)(t.h2,{id:"reposting-a-post",children:"Reposting a post"}),"\n",(0,s.jsx)(t.p,{children:"Reposting and un-reposting looks almost exactly the same as liking and\nunliking."}),"\n",(0,s.jsxs)(l.A,{groupId:"sdk",children:[(0,s.jsx)(o.A,{value:"ts",label:"TypeScript",children:(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-typescript",metastring:'title="repost"',children:" import { repost } from '@bsky/sdk'\n\n const { uri: repostUri } = await client.call(repost, { uri, cid })\n"})})}),(0,s.jsx)(o.A,{value:"python",label:"Python",children:(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-python",metastring:'title="client.repost"',children:" uri = client.repost(uri=uri, cid=cid).uri\n"})})}),(0,s.jsxs)(o.A,{value:"go",label:"Go",children:[(0,s.jsxs)(t.p,{children:["Same pattern as a like, with the ",(0,s.jsx)(t.code,{children:"app.bsky.feed.repost"})," collection:"]}),(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-go",children:'repost := &appbsky.FeedRepost{\n CreatedAt: time.Now().UTC().Format(time.RFC3339),\n Subject: &comatproto.RepoStrongRef{Uri: uri, Cid: cid},\n}\nresp, _ := comatproto.RepoCreateRecord(ctx, client, &comatproto.RepoCreateRecord_Input{\n Repo: client.AccountDID.String(),\n Collection: "app.bsky.feed.repost",\n Record: &lexutil.LexiconTypeDecoder{Val: repost},\n})\n'})})]})]}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{children:"Parameter"}),(0,s.jsx)(t.th,{children:"Type"}),(0,s.jsx)(t.th,{children:"Description"}),(0,s.jsx)(t.th,{children:"Required"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:(0,s.jsx)(t.code,{children:"uri"})}),(0,s.jsx)(t.td,{children:(0,s.jsx)(t.code,{children:"string"})}),(0,s.jsx)(t.td,{children:"The URI of the post"}),(0,s.jsx)(t.td,{children:"Yes"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:(0,s.jsx)(t.code,{children:"cid"})}),(0,s.jsx)(t.td,{children:(0,s.jsx)(t.code,{children:"string"})}),(0,s.jsx)(t.td,{children:"The CID of the post"}),(0,s.jsx)(t.td,{children:"Yes"})]})]})]}),"\n",(0,s.jsx)(t.h2,{id:"un-reposting-a-post",children:"Un-reposting a post"}),"\n",(0,s.jsx)(t.p,{children:"Same as unlike, un-reposting a post requires only the post's URI, whose record\nwe want to delete."}),"\n",(0,s.jsxs)(l.A,{groupId:"sdk",children:[(0,s.jsx)(o.A,{value:"ts",label:"TypeScript",children:(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-typescript",metastring:'title="deleteRepost"',children:" import { deleteRepost } from '@bsky/sdk'\n\n await client.call(deleteRepost, repostUri)\n"})})}),(0,s.jsx)(o.A,{value:"python",label:"Python",children:(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-python",metastring:'title="client.delete_repost"',children:" client.delete_repost(uri)\n"})})}),(0,s.jsxs)(o.A,{value:"go",label:"Go",children:[(0,s.jsx)(t.p,{children:"Delete the repost record by its rkey, as with unliking:"}),(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-go",children:'rkey := uri[strings.LastIndex(uri, "/")+1:]\ncomatproto.RepoDeleteRecord(ctx, client, &comatproto.RepoDeleteRecord_Input{\n Repo: client.AccountDID.String(),\n Collection: "app.bsky.feed.repost",\n Rkey: rkey,\n})\n'})})]})]}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{children:"Parameter"}),(0,s.jsx)(t.th,{children:"Type"}),(0,s.jsx)(t.th,{children:"Description"}),(0,s.jsx)(t.th,{children:"Required"})]})}),(0,s.jsx)(t.tbody,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:(0,s.jsx)(t.code,{children:"uri"})}),(0,s.jsx)(t.td,{children:(0,s.jsx)(t.code,{children:"string"})}),(0,s.jsx)(t.td,{children:"The URI of the repost record to delete"}),(0,s.jsx)(t.td,{children:"Yes"})]})})]}),"\n",(0,s.jsx)(t.h2,{id:"quote-reposting",children:"Quote reposting"}),"\n",(0,s.jsx)(t.admonition,{type:"info",children:(0,s.jsxs)(t.p,{children:["For information on quote posts, see the ",(0,s.jsx)(t.a,{href:"/docs/bluesky-api/creating-a-post#quote-posts",children:"Create a\npost"})," tutorial."]})}),"\n",(0,s.jsx)(t.hr,{}),"\n",(0,s.jsxs)("span",{class:"docsFooterNote",children:["Looking for more? Browse additional tutorials and guides on ",(0,s.jsx)(t.a,{href:"https://atproto.com/guides/tutorials",children:"atproto.com"}),"."]})]})}function p(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(h,{...e})}):h(e)}},9608(e,t,r){r.d(t,{A:()=>a});r(6540);var n=r(8215),s=r(8626);const i="tabItem_Ymn6";var l=r(4848);function o({children:e,className:t,hidden:r}){return(0,l.jsx)("div",{role:"tabpanel",className:(0,n.A)(i,t),hidden:r,children:e})}function a({children:e,className:t,value:r}){const{selectedValue:n,lazy:i}=(0,s.uc)(),a=r===n;return!a&&i?null:(0,l.jsx)(o,{className:t,hidden:!a,children:e})}},5645(e,t,r){r.d(t,{A:()=>x});r(6540);var n=r(8215),s=r(8630),i=r(8626),l=r(4245),o=r(1062);const a="tabList__CuJ",c="tabItem_LNqP";var d=r(4848);function u({className:e}){const{selectedValue:t,selectValue:r,tabValues:s,block:o}=(0,i.uc)(),a=[],{blockElementScrollPositionUntilNextRender:u}
1=(0,l.a_)(),h=e=>{const n=e.currentTarget,i=a.indexOf(n),l=s[i].value;l!==t&&(u(n),r(l))},p=e=>{let t=null;switch(e.key){case"Enter":h(e);break;case"ArrowRight":{const r=a.indexOf(e.currentTarget)+1;t=a[r]??a[0];break}case"ArrowLeft":{const r=a.indexOf(e.currentTarget)-1;t=a[r]??a[a.length-1];break}}t?.focus()};return(0,d.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,n.A)("tabs",{"tabs--block":o},e),children:s.map((({value:e,label:r,attributes:s})=>(0,d.jsx)("li",{role:"tab",tabIndex:t===e?0:-1,"aria-selected":t===e,ref:e=>{a.push(e)},onKeyDown:p,onClick:h,...s,className:(0,n.A)("tabs__item",c,s?.className,{"tabs__item--active":t===e}),children:r??e},e)))})}function h({children:e}){return(0,d.jsx)("div",{className:"margin-top--md",children:e})}function p({className:e,children:t}){return(0,d.jsxs)("div",{className:(0,n.A)(s.G.tabs.container,"tabs-container",a),children:[(0,d.jsx)(u,{className:e}),(0,d.jsx)(h,{children:t})]})}function x(e){const t=(0,o.A)(),r=(0,i.OC)(e);return(0,d.jsx)(i.O_,{value:r,children:(0,d.jsx)(p,{className:e.className,children:(0,i.vT)(e.children)})},String(t))}},8626(e,t,r){r.d(t,{OC:()=>x,O_:()=>m,uc:()=>g,vT:()=>d});var n=r(6540),s=r(6347),i=r(6494),l=r(2814),o=r(9900),a=r(5167),c=r(4848);function d(e){return n.Children.toArray(e).filter((e=>"\n"!==e))}function u(e){const{values:t,children:r}=e;return(0,n.useMemo)((()=>{const e=t??function(e){return n.Children.toArray(e).flatMap((e=>{if(!e)return[];if((0,n.isValidElement)(e)&&function(e){const{props:t}=e;return!!t&&"object"==typeof t&&"value"in t}(e))return[e];const t="string"==typeof e.type?e.type:e.type.name;throw new Error(`Docusaurus error: Bad <Tabs> child <${t}>: all children of the <Tabs> component should be <TabItem>, and every <TabItem> should have a unique "value" prop.\nIf you do not want to pass on a "value" prop to the direct children of <Tabs>, you can also pass an explicit <Tabs values={...}> prop.`)})).map((({props:{value:e,label:t,attributes:r,default:n}})=>({value:e,label:t,attributes:r,default:n})))}(r);return function(e){const t=(0,a.XI)(e,((e,t)=>e.value===t.value));if(t.length>0)throw new Error(`Docusaurus error: Duplicate values "${t.map((e=>`'${e.value}'`)).join(", ")}" found in <Tabs>. Every value needs to be unique.`)}(e),e}),[t,r])}function h({value:e,tabValues:t}){return t.some((t=>t.value===e))}function p({queryString:e=!1,groupId:t}){const r=(0,s.W6)(),i=function({queryString:e=!1,groupId:t}){if("string"==typeof e)return e;if(!1===e)return null;if(!0===e&&!t)throw new Error('Docusaurus error: The <Tabs> component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return t??null}({queryString:e,groupId:t});return[(0,l.aZ)(i),(0,n.useCallback)((e=>{if(!i)return;const t=new URLSearchParams(r.location.search);t.set(i,e),r.replace({...r.location,search:t.toString()})}),[i,r])]}function x(e){const{defaultValue:t,queryString:r=!1,groupId:s}=e,l=u(e),[a,c]=(0,n.useState)((()=>function({defaultValue:e,tabValues:t}){if(0===t.length)throw new Error("Docusaurus error: the <Tabs> component requires at least one <TabItem> children component");if(e){if(!h({value:e,tabValues:t}))throw new Error(`Docusaurus error: The <Tabs> has a defaultValue "${e}" but none of its children has the corresponding value. Available values are: ${t.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return e}const r=t.find((e=>e.default))??t[0];if(!r)throw new Error("Unexpected error: 0 tabValues");return r.value}({defaultValue:t,tabValues:l}))),[d,x]=p({queryString:r,groupId:s}),[j,g]=function({groupId:e}){const t=function(e){return e?`docusaurus.tab.${e}`:null}(e),[r,s]=(0,o.Dv)(t);return[r,(0,n.useCallback)((e=>{t&&s.set(e)}),[t,s])]}({groupId:s}),m=(()=>{const e=d??j;return h({value:e,tabValues:l})?e:null})();(0,i.A)((()=>{m&&c(m)}),[m]);return{selectedValue:a,selectValue:(0,n.useCallback)((e=>{if(!h({value:e,tabValues:l}))throw new Error(`Can't select invalid tab value=${e}`);c(e),x(e),g(e)}),[x,g,l]),tabValues:l,lazy:e.lazy??!1,block:e.block??!1}}const j=(0,n.createContext)(null);function g(){const e=n.useContext(j);if(!e)throw new Error("useTabsContext() must be used within a Tabs component");return e}function m(e){return(0,c.jsx)(j.Provider,{value:e.value,children:e.children})}},8453(e,t,r){r.d(t,{R:()=>l,x:()=>o});var n=r(6540);const s={},i=n.createContext(s);function l(e){const t=n.useContext(i);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:l(e.components),n.createElement(i.Provider,{value:t},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.