add files
This commit is contained in:
commit
04e29ed525
7 changed files with 1337 additions and 0 deletions
227
bsky/bluesky.go
Normal file
227
bsky/bluesky.go
Normal file
|
@ -0,0 +1,227 @@
|
|||
package bsky
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/charmbracelet/log"
|
||||
"github.com/dghubble/sling"
|
||||
)
|
||||
|
||||
type BlueskyConfig struct {
|
||||
PDSURL string `json:"pds-url"`
|
||||
Repo string `json:"repo"`
|
||||
Handle string `json:"handle"`
|
||||
DID string `json:"did"`
|
||||
AppPassword string `json:"app-password"`
|
||||
AccessJWT string `json:"access-jwt"`
|
||||
RefreshJWT string `json:"refresh-jwt"`
|
||||
Cursor int64 `json:"cursor"`
|
||||
}
|
||||
|
||||
type DIDResponse struct {
|
||||
Context []string `json:"@context"`
|
||||
ID string `json:"id"`
|
||||
AlsoKnownAs []string `json:"alsoKnownAs"`
|
||||
VerificationMethod []struct {
|
||||
ID string `json:"id"`
|
||||
Type string `json:"type"`
|
||||
Controller string `json:"controller"`
|
||||
PublicKeyMultibase string `json:"publicKeyMultibase"`
|
||||
} `json:"verificationMethod"`
|
||||
Service []struct {
|
||||
ID string `json:"id"`
|
||||
Type string `json:"type"`
|
||||
ServiceEndpoint string `json:"serviceEndpoint"`
|
||||
} `json:"service"`
|
||||
}
|
||||
|
||||
type BSkySessionResponse struct {
|
||||
AccessJWT string `json:"accessJwt,omitempty"`
|
||||
RefreshJWT string `json:"refreshJwt,omitempty"`
|
||||
Handle string `json:"handle"`
|
||||
DID string `json:"did"`
|
||||
Error string `json:"error,omitempty"`
|
||||
Message string `json:"message,omitempty"`
|
||||
}
|
||||
|
||||
type CommitResponse struct {
|
||||
URI string `json:"uri"`
|
||||
Cid string `json:"cid"`
|
||||
Commit struct {
|
||||
Cid string `json:"cid"`
|
||||
Rev string `json:"rev"`
|
||||
} `json:"commit"`
|
||||
Error string `json:"error"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
func (c *CommitResponse) GetRKey() string {
|
||||
s := strings.SplitN(c.URI, "/", 5)
|
||||
if len(s) == 5 {
|
||||
return s[4]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type Link struct {
|
||||
Cid string `json:"cid"`
|
||||
URI string `json:"uri"`
|
||||
}
|
||||
|
||||
type Bluesky struct {
|
||||
Cfg *BlueskyConfig
|
||||
HttpClient *http.Client
|
||||
Logger *log.Logger
|
||||
sling *sling.Sling
|
||||
}
|
||||
|
||||
func (bluesky *Bluesky) CreateSession(cfg *BlueskyConfig) error {
|
||||
body := struct {
|
||||
Identifier string `json:"identifier"`
|
||||
Password string `json:"password"`
|
||||
}{
|
||||
Identifier: cfg.Handle,
|
||||
Password: cfg.AppPassword,
|
||||
}
|
||||
resp := new(BSkySessionResponse)
|
||||
|
||||
bluesky.sling.New().Post("/xrpc/com.atproto.server.createSession").BodyJSON(body).ReceiveSuccess(resp)
|
||||
if resp.AccessJWT != "" {
|
||||
cfg.AccessJWT = resp.AccessJWT
|
||||
cfg.RefreshJWT = resp.RefreshJWT
|
||||
return nil
|
||||
}
|
||||
|
||||
bluesky.sling.New().Set("Authorization", fmt.Sprintf("Bearer %s", bluesky.Cfg.AccessJWT))
|
||||
return errors.New("unable to authenticate, check handle/password")
|
||||
}
|
||||
|
||||
func (bluesky *Bluesky) RefreshSession() error {
|
||||
resp := new(BSkySessionResponse)
|
||||
|
||||
bluesky.sling.New().Set("Authorization", fmt.Sprintf("Bearer %s", bluesky.Cfg.RefreshJWT)).
|
||||
Post("/xrpc/com.atproto.server.refreshSession").Receive(resp, resp)
|
||||
if resp.AccessJWT != "" {
|
||||
bluesky.Cfg.AccessJWT = resp.AccessJWT
|
||||
bluesky.Cfg.RefreshJWT = resp.RefreshJWT
|
||||
PersistAuthSession(bluesky.Cfg)
|
||||
bluesky.sling.Set("Authorization", fmt.Sprintf("Bearer %s", bluesky.Cfg.AccessJWT))
|
||||
return nil
|
||||
}
|
||||
|
||||
return bluesky.CreateSession(bluesky.Cfg)
|
||||
}
|
||||
|
||||
func (bluesky *Bluesky) CheckSessionValid() {
|
||||
resp := new(BSkySessionResponse)
|
||||
|
||||
bluesky.sling.New().Set("Authorization", fmt.Sprintf("Bearer %s", bluesky.Cfg.AccessJWT)).
|
||||
Get("/xrpc/app.bsky.actor.getProfile").Receive(resp, resp)
|
||||
if resp.Error == "ExpiredToken" {
|
||||
bluesky.RefreshSession()
|
||||
}
|
||||
}
|
||||
|
||||
type TelegramRecord struct {
|
||||
ChannelID int64 `json:"channel_id"`
|
||||
MessageID int `json:"message_id"`
|
||||
Link *Link `json:"link"`
|
||||
Error string `json:"error"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
func (bluesky *Bluesky) CommitTelegramResponse(data *TelegramRecord, rkey string) *CommitResponse {
|
||||
bluesky.CheckSessionValid()
|
||||
|
||||
resp := new(CommitResponse)
|
||||
|
||||
record := struct {
|
||||
Repo string `json:"repo"`
|
||||
Collection string `json:"collection"`
|
||||
RKey string `json:"rkey"`
|
||||
Record TelegramRecord `json:"record"`
|
||||
}{
|
||||
Repo: bluesky.Cfg.DID,
|
||||
Collection: "blue.zio.bsky2tg.post",
|
||||
RKey: rkey,
|
||||
Record: TelegramRecord{
|
||||
ChannelID: data.ChannelID,
|
||||
MessageID: data.MessageID,
|
||||
Link: &Link{
|
||||
Cid: data.Link.Cid,
|
||||
URI: data.Link.URI,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
bluesky.sling.New().Set("Authorization", fmt.Sprintf("Bearer %s", bluesky.Cfg.AccessJWT)).
|
||||
Post("/xrpc/com.atproto.repo.createRecord").BodyJSON(&record).Receive(resp, resp)
|
||||
return resp
|
||||
}
|
||||
|
||||
func (bluesky *Bluesky) GetTelegramData(rkey string) (*TelegramRecord, string) {
|
||||
resp := &struct {
|
||||
Value *TelegramRecord `json:"value"`
|
||||
URI string `json:"uri"`
|
||||
Cid string `json:"cid"`
|
||||
Error string `json:"error"`
|
||||
Message string `json:"message"`
|
||||
}{}
|
||||
|
||||
params := struct {
|
||||
Repo string `url:"repo"`
|
||||
Collection string `url:"collection"`
|
||||
RKey string `url:"rkey"`
|
||||
}{
|
||||
Repo: bluesky.Cfg.DID,
|
||||
Collection: "blue.zio.bsky2tg.post",
|
||||
RKey: rkey,
|
||||
}
|
||||
|
||||
bluesky.sling.New().Get("/xrpc/com.atproto.repo.getRecord").QueryStruct(¶ms).Receive(resp, resp)
|
||||
return resp.Value, resp.Message
|
||||
}
|
||||
|
||||
func (bluesky *Bluesky) GetPost(uri string) *Post {
|
||||
bluesky.CheckSessionValid()
|
||||
var post = struct {
|
||||
URI string `json:"uri"`
|
||||
CID string `json:"cid"`
|
||||
Value *Post `json:"value"`
|
||||
}{}
|
||||
|
||||
args := strings.SplitN(uri, "/", 5)
|
||||
params := struct {
|
||||
RKey string `url:"rkey"`
|
||||
Repo string `url:"repo"`
|
||||
Collection string `url:"collection"`
|
||||
}{
|
||||
RKey: args[4],
|
||||
Repo: args[2],
|
||||
Collection: args[3],
|
||||
}
|
||||
bluesky.sling.New().Get("/xrpc/com.atproto.repo.getRecord").QueryStruct(params).ReceiveSuccess(&post)
|
||||
|
||||
return post.Value
|
||||
}
|
||||
|
||||
func (bluesky *Bluesky) DeleteRecord(args []string) *CommitResponse {
|
||||
bluesky.CheckSessionValid()
|
||||
|
||||
resp := new(CommitResponse)
|
||||
params := struct {
|
||||
RKey string `url:"rkey"`
|
||||
Repo string `url:"repo"`
|
||||
Collection string `url:"collection"`
|
||||
}{
|
||||
RKey: args[0],
|
||||
Repo: args[1],
|
||||
Collection: args[2],
|
||||
}
|
||||
bluesky.sling.New().Set("Authorization", fmt.Sprintf("Bearer %s", bluesky.Cfg.AccessJWT)).
|
||||
Get("/xrpc/com.atproto.repo.deleteRecord").QueryStruct(params).ReceiveSuccess(resp)
|
||||
return resp
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue