Skip to content

Commit ba39a4f

Browse files
authored
feat: analytics
Merge pull request #28 from Preloading/analytics
2 parents b54bacd + 1a99c64 commit ba39a4f

6 files changed

Lines changed: 114 additions & 8 deletions

File tree

bridge/bridge.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,11 +121,11 @@ type TwitterUser struct {
121121

122122
type TwitterActivitiySummary struct {
123123
Favourites []int64 `json:"favoriters"` // Pretty sure this is the User ID of the favouriters
124-
FavouritesCount int `json:"favoriters_count"`
124+
FavouritesCount string `json:"favoriters_count"`
125125
Repliers []int64 `json:"repliers"`
126-
RepliersCount int `json:"repliers_count"`
126+
RepliersCount string `json:"repliers_count"`
127127
Retweets []int64 `json:"retweeters"`
128-
RetweetsCount int `json:"retweeters_count"`
128+
RetweetsCount string `json:"retweeters_count"`
129129
}
130130

131131
type MediaSize struct {

db_controller/db_controller.go

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,23 @@ type MessageContext struct {
7171
TimelineContext string `gorm:"type:string;not null"`
7272
}
7373

74+
// Analytics seems cool, and me liek numbrers.
75+
76+
type AnalyticData struct {
77+
DataType string `gorm:"type:string;not null"`
78+
IPAddress string `gorm:"type:string;"`
79+
Language string `gorm:"type:string;"`
80+
UserAgent string `gorm:"type:string;"`
81+
TwitterClient string `gorm:"type:string"`
82+
TwitterClientVersion string `gorm:"type:string"`
83+
Timestamp time.Time `gorm:"type:timestamp"`
84+
}
85+
7486
var db *gorm.DB
87+
var cfg config.Config
7588

76-
func InitDB(cfg config.Config) {
89+
func InitDB(_cfg config.Config) {
90+
cfg = _cfg
7791
// Ensure the directory exists
7892
dbDir := filepath.Dir(cfg.DatabasePath)
7993
if err := os.MkdirAll(dbDir, os.ModePerm); err != nil {
@@ -101,6 +115,7 @@ func InitDB(cfg config.Config) {
101115
db.AutoMigrate(&Token{})
102116
db.AutoMigrate(&MessageContext{})
103117
db.AutoMigrate(&TwitterIDs{})
118+
db.AutoMigrate(&AnalyticData{})
104119
}
105120

106121
// StoreToken stores an encrypted access token and refresh token in the database.
@@ -239,3 +254,19 @@ func GetTwitterIDFromDatabase(twitterID *int64) (*string, *time.Time, *string, e
239254

240255
return &blueskyID.BlueskyID, blueskyID.DateCreated, blueskyID.ReposterDid, nil
241256
}
257+
258+
// Stores analytic data (if enabled)
259+
// -- TYPES --
260+
// 1. "login"
261+
// 2. "tweets viewed"
262+
// 3. "tweets posted"
263+
func StoreAnalyticData(data AnalyticData) {
264+
if !cfg.TrackAnalytics {
265+
return
266+
}
267+
268+
result := db.Create(&data)
269+
if result.Error != nil {
270+
fmt.Println("Failed to store analytic data:", result.Error)
271+
}
272+
}

twitterv1/auth.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,16 @@ func access_token(c *fiber.Ctx) error {
6161

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

64+
db_controller.StoreAnalyticData(db_controller.AnalyticData{
65+
DataType: "auth",
66+
IPAddress: c.IP(),
67+
UserAgent: c.Get("User-Agent"),
68+
Language: c.Get("Accept-Language"),
69+
TwitterClient: c.Get("X-Twitter-Client"),
70+
TwitterClientVersion: c.Get("X-Twitter-Client-Version"),
71+
Timestamp: time.Now(),
72+
})
73+
6474
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))
6575
}
6676
// 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.

twitterv1/interaction.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88

99
blueskyapi "github.com/Preloading/MastodonTwitterAPI/bluesky"
1010
"github.com/Preloading/MastodonTwitterAPI/bridge"
11+
"github.com/Preloading/MastodonTwitterAPI/db_controller"
1112
"github.com/gofiber/fiber/v2"
1213
)
1314

@@ -44,6 +45,16 @@ func status_update(c *fiber.Ctx) error {
4445
return c.Status(fiber.StatusInternalServerError).SendString("Failed to update status")
4546
}
4647

48+
db_controller.StoreAnalyticData(db_controller.AnalyticData{
49+
DataType: "status_update",
50+
IPAddress: c.IP(),
51+
UserAgent: c.Get("User-Agent"),
52+
Language: c.Get("Accept-Language"),
53+
TwitterClient: c.Get("X-Twitter-Client"),
54+
TwitterClientVersion: c.Get("X-Twitter-Client-Version"),
55+
Timestamp: time.Now(),
56+
})
57+
4758
if thread.Thread.Parent == nil {
4859
return EncodeAndSend(c, TranslatePostToTweet(thread.Thread.Post, "", "", nil, nil, *oauthToken, *pds))
4960
} else {
@@ -91,6 +102,16 @@ func retweet(c *fiber.Ctx) error {
91102
retweet.IDStr = strconv.FormatInt(retweet.ID, 10)
92103
originalPost.Thread.Post.Viewer.Repost = blueskyRepostURI
93104

105+
db_controller.StoreAnalyticData(db_controller.AnalyticData{
106+
DataType: "retweeted",
107+
IPAddress: c.IP(),
108+
UserAgent: c.Get("User-Agent"),
109+
Language: c.Get("Accept-Language"),
110+
TwitterClient: c.Get("X-Twitter-Client"),
111+
TwitterClientVersion: c.Get("X-Twitter-Client-Version"),
112+
Timestamp: time.Now(),
113+
})
114+
94115
return EncodeAndSend(c, bridge.Retweet{
95116
Tweet: retweet,
96117
RetweetedStatus: func() bridge.Tweet { // TODO: make this respond with proper retweet data
@@ -139,6 +160,16 @@ func favourite(c *fiber.Ctx) error {
139160
newTweet = TranslatePostToTweet(post.Thread.Post, post.Thread.Parent.Post.URI, post.Thread.Parent.Post.Author.DID, &post.Thread.Parent.Post.Record.CreatedAt, nil, *oauthToken, *pds)
140161
}
141162

163+
db_controller.StoreAnalyticData(db_controller.AnalyticData{
164+
DataType: "favorited",
165+
IPAddress: c.IP(),
166+
UserAgent: c.Get("User-Agent"),
167+
Language: c.Get("Accept-Language"),
168+
TwitterClient: c.Get("X-Twitter-Client"),
169+
TwitterClientVersion: c.Get("X-Twitter-Client-Version"),
170+
Timestamp: time.Now(),
171+
})
172+
142173
return EncodeAndSend(c, newTweet)
143174
}
144175

@@ -176,6 +207,16 @@ func Unfavourite(c *fiber.Ctx) error { // yes i am canadian
176207
newTweet = TranslatePostToTweet(post.Thread.Post, post.Thread.Parent.Post.URI, post.Thread.Parent.Post.Author.DID, &post.Thread.Parent.Post.Record.CreatedAt, nil, *oauthToken, *pds)
177208
}
178209

210+
db_controller.StoreAnalyticData(db_controller.AnalyticData{
211+
DataType: "unfavorite",
212+
IPAddress: c.IP(),
213+
UserAgent: c.Get("User-Agent"),
214+
Language: c.Get("Accept-Language"),
215+
TwitterClient: c.Get("X-Twitter-Client"),
216+
TwitterClientVersion: c.Get("X-Twitter-Client-Version"),
217+
Timestamp: time.Now(),
218+
})
219+
179220
return EncodeAndSend(c, newTweet)
180221
}
181222

@@ -225,6 +266,16 @@ func DeleteTweet(c *fiber.Ctx) error {
225266
return c.Status(fiber.StatusInternalServerError).SendString("Failed to delete post")
226267
}
227268

269+
db_controller.StoreAnalyticData(db_controller.AnalyticData{
270+
DataType: "deleted_post",
271+
IPAddress: c.IP(),
272+
UserAgent: c.Get("User-Agent"),
273+
Language: c.Get("Accept-Language"),
274+
TwitterClient: c.Get("X-Twitter-Client"),
275+
TwitterClientVersion: c.Get("X-Twitter-Client-Version"),
276+
Timestamp: time.Now(),
277+
})
278+
228279
postToDelete.Thread.Post.URI = postId
229280
postToDelete.Thread.Post.Author.DID = *user_did
230281

twitterv1/post_viewing.go

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99

1010
blueskyapi "github.com/Preloading/MastodonTwitterAPI/bluesky"
1111
"github.com/Preloading/MastodonTwitterAPI/bridge"
12+
"github.com/Preloading/MastodonTwitterAPI/db_controller"
1213
"github.com/gofiber/fiber/v2"
1314
)
1415

@@ -227,6 +228,19 @@ func GetStatusFromId(c *fiber.Ctx) error {
227228

228229
// https://web.archive.org/web/20120506182126/https://dev.twitter.com/docs/platform-objects/tweets
229230
func TranslatePostToTweet(tweet blueskyapi.Post, replyMsgBskyURI string, replyUserBskyId string, replyTimeStamp *time.Time, postReason *blueskyapi.PostReason, token string, pds string) bridge.Tweet {
231+
if len(tweet.Record.Langs) > 0 {
232+
db_controller.StoreAnalyticData(db_controller.AnalyticData{
233+
DataType: "postviewing",
234+
Timestamp: time.Now(),
235+
Language: tweet.Record.Langs[0],
236+
})
237+
} else {
238+
db_controller.StoreAnalyticData(db_controller.AnalyticData{
239+
DataType: "postviewing",
240+
Timestamp: time.Now(),
241+
})
242+
}
243+
230244
tweetEntities := bridge.Entities{
231245
Hashtags: nil,
232246
Urls: nil,
@@ -524,9 +538,9 @@ func TweetInfo(c *fiber.Ctx) error {
524538
}
525539

526540
return EncodeAndSend(c, bridge.TwitterActivitiySummary{
527-
FavouritesCount: thread.Thread.Post.LikeCount,
528-
RetweetsCount: thread.Thread.Post.RepostCount,
529-
RepliersCount: thread.Thread.Post.ReplyCount,
541+
FavouritesCount: strconv.Itoa(thread.Thread.Post.LikeCount),
542+
RetweetsCount: strconv.Itoa(thread.Thread.Post.RepostCount),
543+
RepliersCount: strconv.Itoa(thread.Thread.Post.ReplyCount),
530544
Favourites: favourites,
531545
Retweets: retweeters,
532546
Repliers: repliers,

twitterv1/twitterv1.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ func InitServer(config *config.Config) {
3333
// fmt.Println("Request Method:", c.Method())
3434
fmt.Println("Request URL:", c.OriginalURL())
3535
// fmt.Println("Post Body:", string(c.Body()))
36-
// fmt.Println("Headers:", string(c.Request().Header.Header()))
36+
fmt.Println("Headers:", string(c.Request().Header.Header()))
3737
// fmt.Println()
3838
return c.Next()
3939
})

0 commit comments

Comments
 (0)