@@ -22,6 +22,9 @@ def post(self):
2222 def register (self , clientname ):
2323 raise NotImplementedError
2424
25+ def set_pin (self , postid ):
26+ raise NotImplementedError
27+
2528
2629class Mastodon (SocialPoster ):
2730 name = 'mastodon'
@@ -42,6 +45,57 @@ def post(self, text):
4245
4346 return r .json ()['id' ]
4447
48+ def set_pin (self , postid ):
49+ # First we have to see if there is an existing pin that has to be removed. To do that, we
50+ # have to fetch our account id.
51+ r = requests .get (
52+ '{}/api/v1/accounts/verify_credentials ' .format (self .settings .MASTODON_BASEURL ),
53+ headers = {'Authorization' : 'Bearer {}' .format (self .settings .MASTODON_TOKEN )},
54+ timeout = 10 ,
55+ )
56+ if r .status_code != 200 :
57+ print ("Failed to get mastodon credentials: {}" .format (r .text ))
58+ return False
59+
60+ # Next, get the currently pinned ones
61+ r = requests .get (
62+ '{}/api/v1/accounts/{}/statuses' .format (self .settings .MASTODON_BASEURL , r .json ()['id' ]),
63+ headers = {'Authorization' : 'Bearer {}' .format (self .settings .MASTODON_TOKEN )},
64+ params = {'pinned' : 'true' },
65+ timeout = 10 ,
66+ )
67+ if r .status_code != 200 :
68+ print ("Failed to get list of mastodon pins: {}" .format (r .text ))
69+ return False
70+
71+ found = False
72+ for p in r .json ():
73+ if p ['id' ] == postid :
74+ # Already pinned!
75+ found = True
76+ else :
77+ # This should be unpinned
78+ r2 = requests .post (
79+ '{}/api/v1/statuses{}/unpin' .format (self .settings .MASTODON_BASEURL , p ['id' ]),
80+ headers = {'Authorization' : 'Bearer {}' .format (self .settings .MASTODON_TOKEN )},
81+ timeout = 10 ,
82+ )
83+ if r .status_code != 200 :
84+ print ("Failed to unpin from mastodon: {}" .format (r .text ))
85+
86+ if not found :
87+ # Not already pinned, so pin!
88+ r2 = requests .post (
89+ '{}/api/v1/statuses{}/pin' .format (self .settings .MASTODON_BASEURL , postid ),
90+ headers = {'Authorization' : 'Bearer {}' .format (self .settings .MASTODON_TOKEN )},
91+ timeout = 10 ,
92+ )
93+ if r .status_code != 200 :
94+ print ("Failed to pin to mastodon: {}" .format (r .text ))
95+ return False
96+
97+ return True
98+
4599 def register (self , clientname ):
46100 toadd = io .StringIO ()
47101
@@ -156,6 +210,55 @@ def post(self, text):
156210
157211 return r .json ()['uri' ]
158212
213+ def set_pin (self , postid ):
214+ # Get our profile, so we can "patch" it
215+ r = requests .get (
216+ 'https://bsky.social/xrpc/com.atproto.repo.getRecord' ,
217+ headers = {'Authorization' : 'Bearer {}' .format (self .token )},
218+ params = {'repo' : self .repo , 'collection' : 'app.bsky.actor.profile' , 'rkey' : 'self' },
219+ timeout = 10 ,
220+ )
221+ if r .status_code != 200 :
222+ print ("Failed to get bluesky profile: {}" .format (r .text ))
223+ return False
224+ record = r .json ()['value' ]
225+ if postid :
226+ # We have the uri, but we need both the uri and the cid, so fetch the post
227+ r2 = requests .get (
228+ 'https://bsky.social/xrpc/app.bsky.feed.getPosts' ,
229+ headers = {'Authorization' : 'Bearer {}' .format (self .token )},
230+ params = {'uris' : postid },
231+ timeout = 10 ,
232+ )
233+ if r .status_code != 200 :
234+ print ("Failed to read back bluesky post {}: {}" .format (postid , r .text ))
235+ return False
236+
237+ cid = r2 .json ()['posts' ][0 ]['cid' ]
238+
239+ record ['pinnedPost' ] = {
240+ 'uri' : postid ,
241+ 'cid' : cid ,
242+ }
243+ else :
244+ if 'pinnedPost' in record :
245+ del record ['pinnedPost' ]
246+
247+ if record != r .json ()['value' ]:
248+ # Some changes, so we need to update
249+ r = requests .post (
250+ 'https://bsky.social/xrpc/com.atproto.repo.putRecord' ,
251+ headers = {'Authorization' : 'Bearer {}' .format (self .token )},
252+ json = {'repo' : self .repo , 'collection' : 'app.bsky.actor.profile' , 'rkey' : 'self' , 'record' : record },
253+ timeout = 10 ,
254+ )
255+ if r .status_code != 200 :
256+ print ("Failed to save pack bluesky profile for pinned posts: {}" .format (r .text ))
257+ return False
258+ return True
259+
260+ return True
261+
159262 def register (self , clientname ):
160263 if getattr (self .settings , 'BLUESKY_USER' , None ) is None or getattr (self .settings , 'BLUESKY_PASSWORD' , None ) is None :
161264 return "For bluesky, add an 'app password' from 'Settings' -> 'Privacy and Security'.\n Register the account email as BLUESKY_USER and the app password as BLUESKY_PASSWORD.\n "
0 commit comments