Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions bluesky/blueskyapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"io"
"net/http"
"net/url"
"strconv"
"strings"
"sync"
"time"
Expand Down Expand Up @@ -581,6 +582,7 @@ func GetRelationships(pds string, token string, source string, others []string)
}

func AuthorTTB(author User) *bridge.TwitterUser {
id := bridge.BlueSkyToTwitterID(author.DID)
return &bridge.TwitterUser{
ProfileSidebarFillColor: "e0ff92",
Name: func() string {
Expand All @@ -599,8 +601,8 @@ func AuthorTTB(author User) *bridge.TwitterUser {
ContributorsEnabled: false,
URL: "",
UtcOffset: nil,
ID: bridge.BlueSkyToTwitterID(author.DID),
IDStr: bridge.BlueSkyToTwitterID(author.DID).String(),
ID: *id,
IDStr: strconv.FormatInt(*id, 10),
ProfileUseBackgroundImage: false,
ListedCount: 0,
ProfileTextColor: "000000",
Expand Down Expand Up @@ -857,15 +859,15 @@ func UpdateStatus(pds string, token string, my_did string, status string, in_rep
// add mentions to the facets
if err == nil {
for _, mention := range mentions {
var mentionDID string
var mentionDID *string
for _, user := range mentionedUsers {
if user.ScreenName == mention.Item {
mentionDID = bridge.TwitterIDToBlueSky(*user.ID) // efficency is poor
mentionDID, _ = bridge.TwitterIDToBlueSky(&user.ID) // efficency is poor
break
}
}

if mentionDID == "" {
if mentionDID == nil {
continue
}

Expand All @@ -877,7 +879,7 @@ func UpdateStatus(pds string, token string, my_did string, status string, in_rep
Features: []Feature{
{
Type: "app.bsky.richtext.facet#mention",
Did: mentionDID,
Did: *mentionDID,
},
},
})
Expand Down
274 changes: 104 additions & 170 deletions bridge/bridge.go

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion bridge/authcrypt.go → cryption/authcrypt.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package bridge
package cryption

import (
"crypto/aes"
Expand Down
69 changes: 64 additions & 5 deletions db_controller/db_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ import (
"fmt"
"os"
"path/filepath"
"time"

"strconv"

"github.com/Preloading/MastodonTwitterAPI/bridge"
"github.com/Preloading/MastodonTwitterAPI/config"
authcrypt "github.com/Preloading/MastodonTwitterAPI/cryption"
"github.com/google/uuid"
"gorm.io/driver/mysql"
"gorm.io/driver/postgres"
Expand Down Expand Up @@ -54,6 +57,13 @@ type Token struct {
RefreshExpiry float64 `gorm:"type:float;not null"`
}

type TwitterIDs struct {
BlueskyID string `gorm:"type:string;not null"`
TwitterID string `gorm:"type:string;primaryKey;not null"` // Ensure this has a unique constraint
ReposterDid *string `gorm:"type:string"`
DateCreated *time.Time `gorm:"type:timestamp"`
}

type MessageContext struct {
UserDid string `gorm:"type:string;primaryKey;not null"`
TokenUUID string `gorm:"type:string;primaryKey;not null"`
Expand Down Expand Up @@ -90,6 +100,7 @@ func InitDB(cfg config.Config) {
// Auto-migrate the schema
db.AutoMigrate(&Token{})
db.AutoMigrate(&MessageContext{})
db.AutoMigrate(&TwitterIDs{})
}

// StoreToken stores an encrypted access token and refresh token in the database.
Expand Down Expand Up @@ -124,12 +135,12 @@ func StoreToken(did string, pds string, accessToken string, refreshToken string,
}

func UpdateToken(uuid string, did string, pds string, accessToken string, refreshToken string, encryptionKey string, accessExpiry float64, refreshExpiry float64) (*string, error) {
encryptedAccess, err := bridge.Encrypt(accessToken, encryptionKey)
encryptedAccess, err := authcrypt.Encrypt(accessToken, encryptionKey)
if err != nil {
return nil, fmt.Errorf("failed to encrypt access token: %v", err)
}

encryptedRefresh, err := bridge.Encrypt(refreshToken, encryptionKey)
encryptedRefresh, err := authcrypt.Encrypt(refreshToken, encryptionKey)
if err != nil {
return nil, fmt.Errorf("failed to encrypt refresh token: %v", err)
}
Expand Down Expand Up @@ -168,15 +179,63 @@ func GetToken(did string, tokenUUID string, encryptionKey string) (*string, *str
return nil, nil, nil, nil, nil, err
}

accessToken, err := bridge.Decrypt(token.EncryptedAccessToken, encryptionKey)
accessToken, err := authcrypt.Decrypt(token.EncryptedAccessToken, encryptionKey)
if err != nil {
return nil, nil, nil, nil, nil, err
}

refreshToken, err := bridge.Decrypt(token.EncryptedRefreshToken, encryptionKey)
refreshToken, err := authcrypt.Decrypt(token.EncryptedRefreshToken, encryptionKey)
if err != nil {
return nil, nil, nil, nil, nil, err
}

return &accessToken, &refreshToken, &token.AccessExpiry, &token.RefreshExpiry, &token.UserPDS, nil
}

// Stores ID data in the database.
// @params: twitterID, blueskyID, dateCreated, reposterDid
// @results: error
func StoreTwitterIdInDatabase(twitterID *int64, blueskyId string, dateCreated *time.Time, reposterDid *string) error {
if twitterID == nil {
return fmt.Errorf("twitterID is nil")
}

storedData := TwitterIDs{
TwitterID: strconv.FormatInt(*twitterID, 10), // Convert *int64 to string
BlueskyID: blueskyId,
DateCreated: dateCreated,
ReposterDid: reposterDid,
}

result := db.Clauses(clause.OnConflict{
Columns: []clause.Column{
{Name: "twitter_id"},
},
UpdateAll: true,
}).Create(&storedData)

if result.Error != nil {
// If there's an error, try updating the existing record
fmt.Println("Error:", result.Error)
panic(result.Error)
//return db.Model(&TwitterIDs{}).Where("twitter_id = ?", strconv.FormatUint(twitterID, 10)).Updates(storedData).Error
}

return nil
}

// Gets a twitter id from the database
// @params: twitterID
// @results: blueskyID, dateCreated, reposterDid, error
func GetTwitterIDFromDatabase(twitterID *int64) (*string, *time.Time, *string, error) {
if twitterID == nil {
return nil, nil, nil, fmt.Errorf("twitterID is nil")
}

var blueskyID TwitterIDs
if err := db.Where("twitter_id = ?", strconv.FormatInt(*twitterID, 10)).First(&blueskyID).Error; err != nil {
return nil, nil, nil, err
}

return &blueskyID.BlueskyID, blueskyID.DateCreated, blueskyID.ReposterDid, nil
}
19 changes: 10 additions & 9 deletions twitterv1/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

blueskyapi "github.com/Preloading/MastodonTwitterAPI/bluesky"
"github.com/Preloading/MastodonTwitterAPI/bridge"
"github.com/Preloading/MastodonTwitterAPI/cryption"
"github.com/Preloading/MastodonTwitterAPI/db_controller"
"github.com/gofiber/fiber/v2"
)
Expand All @@ -31,18 +32,18 @@ func access_token(c *fiber.Ctx) error {
}

// Our bluesky authentication was sucessful! Now we should store the auth info, encryted, in the DB
encryptionkey, err := bridge.GenerateKey()
encryptionkey, err := cryption.GenerateKey()
if err != nil {
fmt.Println("Error:", err)
return c.SendStatus(500)
}

access_token_expiry, err := bridge.GetJWTTokenExpirationUnix(res.AccessJwt)
access_token_expiry, err := cryption.GetJWTTokenExpirationUnix(res.AccessJwt)
if err != nil {
fmt.Println("Error:", err)
return c.SendStatus(500)
}
refresh_token_expiry, err := bridge.GetJWTTokenExpirationUnix(res.RefreshJwt)
refresh_token_expiry, err := cryption.GetJWTTokenExpirationUnix(res.RefreshJwt)
if err != nil {
fmt.Println("Error:", err)
return c.SendStatus(500)
Expand All @@ -58,9 +59,9 @@ func access_token(c *fiber.Ctx) error {
encryptionkey = strings.ReplaceAll(encryptionkey, "/", "_")
encryptionkey = strings.ReplaceAll(encryptionkey, "=", "") // remove padding

oauth_token := fmt.Sprintf("%s.%s.%s", bridge.Base64URLEncode(res.DID), bridge.Base64URLEncode(*uuid), encryptionkey)
oauth_token := fmt.Sprintf("%s.%s.%s", cryption.Base64URLEncode(res.DID), cryption.Base64URLEncode(*uuid), encryptionkey)

return c.SendString(fmt.Sprintf("oauth_token=%s&oauth_token_secret=%s&user_id=%s&screen_name=twitterapi&x_auth_expires=%f", oauth_token, oauth_token, bridge.BlueSkyToTwitterID(res.DID).String(), *access_token_expiry))
return c.SendString(fmt.Sprintf("oauth_token=%s&oauth_token_secret=%s&user_id=%s&screen_name=twitterapi&x_auth_expires=%f", oauth_token, oauth_token, fmt.Sprintf("%d", bridge.BlueSkyToTwitterID(res.DID)), *access_token_expiry))
}
// We have an unknown request. huh. Probably registration, i'll find a way to send an error msg for that later, as registration is out of scope.
return c.SendStatus(501)
Expand Down Expand Up @@ -109,14 +110,14 @@ func GetAuthFromReq(c *fiber.Ctx) (*string, *string, *string, *string, error) {
// Replace URL-friendly characters with original base64 characters

// Get user DID
userDID, err := bridge.Base64URLDecode(oauthTokenSegments[0])
userDID, err := cryption.Base64URLDecode(oauthTokenSegments[0])

if err != nil {
return nil, &fallbackRoute, nil, nil, err
}

// Get our token UUID. This is used to look up the token in the database.
tokenUUID, err := bridge.Base64URLDecode(oauthTokenSegments[1])
tokenUUID, err := cryption.Base64URLDecode(oauthTokenSegments[1])

if err != nil {
return nil, &fallbackRoute, nil, nil, err
Expand Down Expand Up @@ -157,11 +158,11 @@ func GetAuthFromReq(c *fiber.Ctx) (*string, *string, *string, *string, error) {

accessJwt = &new_auth.AccessJwt

access_token_expiry, err := bridge.GetJWTTokenExpirationUnix(new_auth.AccessJwt)
access_token_expiry, err := cryption.GetJWTTokenExpirationUnix(new_auth.AccessJwt)
if err != nil {
return nil, &fallbackRoute, nil, nil, errors.New("failed to get access token expiry")
}
refresh_token_expiry, err := bridge.GetJWTTokenExpirationUnix(new_auth.RefreshJwt)
refresh_token_expiry, err := cryption.GetJWTTokenExpirationUnix(new_auth.RefreshJwt)
if err != nil {
return nil, &fallbackRoute, nil, nil, errors.New("failed to get refresh token expiry")
}
Expand Down
6 changes: 3 additions & 3 deletions twitterv1/connect.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ func GetMyActivity(c *fiber.Ctx) error {
twitterNotifications = append(twitterNotifications, bridge.MyActivity{
Action: "follow",
CreatedAt: bridge.TwitterTimeConverter(notification.IndexedAt),
ID: bridge.BlueSkyToTwitterID(notification.URI),
ID: *bridge.BlueSkyToTwitterID(notification.URI),
Sources: sources,
})
case "like":
Expand Down Expand Up @@ -133,7 +133,7 @@ func GetMyActivity(c *fiber.Ctx) error {
twitterNotifications = append(twitterNotifications, bridge.MyActivity{
Action: "favorite",
CreatedAt: bridge.TwitterTimeConverter(notification.IndexedAt),
ID: bridge.BlueSkyToTwitterID(notificationId),
ID: *bridge.BlueSkyToTwitterID(notificationId),
Sources: sources,
Targets: []bridge.Tweet{likedTweet},
})
Expand Down Expand Up @@ -178,7 +178,7 @@ func GetMyActivity(c *fiber.Ctx) error {
twitterNotifications = append(twitterNotifications, bridge.MyActivity{
Action: "retweet",
CreatedAt: bridge.TwitterTimeConverter(notification.IndexedAt),
ID: bridge.BlueSkyToTwitterID(notificationId),
ID: *bridge.BlueSkyToTwitterID(notificationId),
Sources: sources,
TargetObjects: []bridge.Tweet{retweetedTweet},
})
Expand Down
16 changes: 7 additions & 9 deletions twitterv1/discover.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package twitterv1

import (
"fmt"
"math/big"
"net/url"
"strconv"
"strings"
"time"

Expand Down Expand Up @@ -32,12 +32,11 @@ func InternalSearch(c *fiber.Ctx) error {
max_id := c.Query("max_id")
var until *time.Time
if max_id != "" {
maxIDBigInt := new(big.Int)
maxIDBigInt, ok := maxIDBigInt.SetString(max_id, 10)
if !ok {
maxIDInt, err := strconv.ParseInt(max_id, 10, 64)
if err != nil {
return c.Status(fiber.StatusBadRequest).SendString("Invalid max_id")
}
_, until, _, err = bridge.TwitterMsgIdToBluesky(maxIDBigInt)
_, until, _, err = bridge.TwitterMsgIdToBluesky(&maxIDInt)
if err != nil {
return c.Status(fiber.StatusBadRequest).SendString("Invalid max_id")
}
Expand All @@ -46,12 +45,11 @@ func InternalSearch(c *fiber.Ctx) error {
var since *time.Time
since_id := c.Query("since_id")
if since_id != "" {
sinceIDBigInt := new(big.Int)
sinceIDBigInt, ok := sinceIDBigInt.SetString(since_id, 10)
if !ok {
sinceIDInt, err := strconv.ParseInt(since_id, 10, 64)
if err != nil {
return c.Status(fiber.StatusBadRequest).SendString("Invalid since_id")
}
_, until, _, err = bridge.TwitterMsgIdToBluesky(sinceIDBigInt)
_, until, _, err = bridge.TwitterMsgIdToBluesky(&sinceIDInt)
if err != nil {
return c.Status(fiber.StatusBadRequest).SendString("Invalid since_id")
}
Expand Down
Loading