store: move the access_hash and username to separate per-user table
Signed-off-by: Sumner Evans <sumner.evans@automattic.com>
This commit is contained in:
@@ -25,7 +25,7 @@ func (t *TelegramClient) getDMChatInfo(ctx context.Context, userID int64) (*brid
|
||||
return nil, err
|
||||
} else if len(users) == 0 {
|
||||
return nil, fmt.Errorf("failed to get user info for user %d", userID)
|
||||
} else if userInfo, err := t.getUserInfoFromTelegramUser(users[0]); err != nil {
|
||||
} else if userInfo, err := t.getUserInfoFromTelegramUser(ctx, users[0]); err != nil {
|
||||
return nil, err
|
||||
} else if err = t.updateGhostWithUserInfo(ctx, userID, userInfo); err != nil {
|
||||
return nil, err
|
||||
|
||||
+30
-13
@@ -247,13 +247,19 @@ func NewTelegramClient(ctx context.Context, tc *TelegramConnector, login *bridge
|
||||
}
|
||||
client.matrixParser = &matrixfmt.HTMLParser{
|
||||
GetGhostDetails: func(ctx context.Context, ui id.UserID) (networkid.UserID, string, int64, bool) {
|
||||
if userID, ok := tc.Bridge.Matrix.ParseGhostMXID(ui); !ok {
|
||||
userID, ok := tc.Bridge.Matrix.ParseGhostMXID(ui)
|
||||
if !ok {
|
||||
return "", "", 0, false
|
||||
} else if ghost, err := tc.Bridge.GetGhostByID(ctx, userID); err != nil {
|
||||
return "", "", 0, false
|
||||
} else {
|
||||
return userID, ghost.Metadata.(*GhostMetadata).Username, ghost.Metadata.(*GhostMetadata).AccessHash, true
|
||||
}
|
||||
telegramUserID, err := ids.ParseUserID(userID)
|
||||
if err != nil {
|
||||
return "", "", 0, false
|
||||
}
|
||||
username, accessHash, found, err := tc.Store.GetScopedStore(telegramUserID).GetUserMetadata(ctx, telegramUserID)
|
||||
if err != nil || !found {
|
||||
return "", "", 0, false
|
||||
}
|
||||
return userID, username, accessHash, true
|
||||
},
|
||||
}
|
||||
|
||||
@@ -330,9 +336,15 @@ func (t *TelegramClient) GetUserInfo(ctx context.Context, ghost *bridgev2.Ghost)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
accessHash, found, err := t.ScopedStore.GetUserAccessHash(ctx, id)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get access hash for user %d: %w", id, err)
|
||||
} else if !found {
|
||||
return nil, fmt.Errorf("access hash not found for user %d", id)
|
||||
}
|
||||
users, err := t.client.API().UsersGetUsers(ctx, []tg.InputUserClass{&tg.InputUser{
|
||||
UserID: id,
|
||||
AccessHash: ghost.Metadata.(*GhostMetadata).AccessHash,
|
||||
AccessHash: accessHash,
|
||||
}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -340,20 +352,28 @@ func (t *TelegramClient) GetUserInfo(ctx context.Context, ghost *bridgev2.Ghost)
|
||||
if len(users) == 0 {
|
||||
return nil, fmt.Errorf("failed to get user info for user %d", id)
|
||||
}
|
||||
userInfo, err := t.getUserInfoFromTelegramUser(users[0])
|
||||
userInfo, err := t.getUserInfoFromTelegramUser(ctx, users[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return userInfo, t.updateGhostWithUserInfo(ctx, id, userInfo)
|
||||
}
|
||||
|
||||
func (t *TelegramClient) getUserInfoFromTelegramUser(u tg.UserClass) (*bridgev2.UserInfo, error) {
|
||||
func (t *TelegramClient) getUserInfoFromTelegramUser(ctx context.Context, u tg.UserClass) (*bridgev2.UserInfo, error) {
|
||||
user, ok := u.(*tg.User)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("user is %T not *tg.User", user)
|
||||
}
|
||||
var identifiers []string
|
||||
if !user.Min {
|
||||
if user.Min {
|
||||
if err := t.ScopedStore.SetUserAccessHash(ctx, user.ID, user.AccessHash); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
if err := t.ScopedStore.SetUserMetadata(ctx, user.ID, user.Username, user.AccessHash); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if username, ok := user.GetUsername(); ok {
|
||||
identifiers = append(identifiers, fmt.Sprintf("telegram:%s", username))
|
||||
}
|
||||
@@ -388,13 +408,10 @@ func (t *TelegramClient) getUserInfoFromTelegramUser(u tg.UserClass) (*bridgev2.
|
||||
ExtraUpdates: func(ctx context.Context, ghost *bridgev2.Ghost) (changed bool) {
|
||||
meta := ghost.Metadata.(*GhostMetadata)
|
||||
if !user.Min {
|
||||
changed = changed || meta.IsPremium != user.Premium || meta.IsBot != user.Bot || meta.Username != user.Username
|
||||
changed = changed || meta.IsPremium != user.Premium || meta.IsBot != user.Bot
|
||||
meta.IsPremium = user.Premium
|
||||
meta.IsBot = user.Bot
|
||||
meta.Username = user.Username
|
||||
}
|
||||
changed = changed || meta.AccessHash != user.AccessHash
|
||||
meta.AccessHash = user.AccessHash
|
||||
return changed
|
||||
},
|
||||
}, nil
|
||||
|
||||
@@ -88,10 +88,8 @@ func (tg *TelegramConnector) GetDBMetaTypes() database.MetaTypes {
|
||||
}
|
||||
|
||||
type GhostMetadata struct {
|
||||
AccessHash int64 `json:"access_hash"`
|
||||
IsPremium bool `json:"is_premium,omitempty"`
|
||||
IsBot bool `json:"is_bot,omitempty"`
|
||||
Username string `json:"username,omitempty"`
|
||||
IsPremium bool `json:"is_premium,omitempty"`
|
||||
IsBot bool `json:"is_bot,omitempty"`
|
||||
}
|
||||
|
||||
type MessageMetadata struct {
|
||||
|
||||
@@ -58,6 +58,32 @@ const (
|
||||
VALUES ($1, $2, $3)
|
||||
ON CONFLICT (user_id, channel_id) DO UPDATE SET access_hash=excluded.access_hash
|
||||
`
|
||||
|
||||
// User Access Hash Queries
|
||||
getUserAccessHashQuery = "SELECT access_hash FROM telegram_user_metadata WHERE receiver_id=$1 AND user_id=$2"
|
||||
setUserAccessHashQuery = `
|
||||
INSERT INTO telegram_user_metadata (receiver_id, user_id, access_hash)
|
||||
VALUES ($1, $2, $3)
|
||||
ON CONFLICT (receiver_id, user_id) DO UPDATE SET access_hash=excluded.access_hash
|
||||
`
|
||||
|
||||
// User Username Queries
|
||||
getUserUsernameQuery = "SELECT username FROM telegram_user_metadata WHERE receiver_id=$1 AND user_id=$2"
|
||||
setUserUsernameQuery = `
|
||||
INSERT INTO telegram_user_metadata (receiver_id, user_id, username)
|
||||
VALUES ($1, $2, $3)
|
||||
ON CONFLICT (receiver_id, user_id) DO UPDATE SET username=excluded.username
|
||||
`
|
||||
|
||||
// User Metadata Queries
|
||||
getUserMetadataQuery = "SELECT username, access_hash FROM telegram_user_metadata WHERE receiver_id=$1 AND user_id=$2"
|
||||
setUserMetadataQuery = `
|
||||
INSERT INTO telegram_user_metadata (receiver_id, user_id, username, access_hash)
|
||||
VALUES ($1, $2, $3, $4)
|
||||
ON CONFLICT (receiver_id, user_id) DO UPDATE SET
|
||||
username=excluded.username,
|
||||
access_hash=excluded.access_hash
|
||||
`
|
||||
)
|
||||
|
||||
var _ session.Storage = (*ScopedStore)(nil)
|
||||
@@ -170,6 +196,45 @@ func (s *ScopedStore) SetChannelAccessHash(ctx context.Context, userID int64, ch
|
||||
return
|
||||
}
|
||||
|
||||
func (s *ScopedStore) GetUserAccessHash(ctx context.Context, userID int64) (accessHash int64, found bool, err error) {
|
||||
err = s.db.QueryRow(ctx, getUserAccessHashQuery, s.telegramUserID, userID).Scan(&accessHash)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return 0, false, nil
|
||||
}
|
||||
return accessHash, err == nil, err
|
||||
}
|
||||
|
||||
func (s *ScopedStore) SetUserAccessHash(ctx context.Context, userID, accessHash int64) (err error) {
|
||||
_, err = s.db.Exec(ctx, setUserAccessHashQuery, s.telegramUserID, userID, accessHash)
|
||||
return
|
||||
}
|
||||
|
||||
func (s *ScopedStore) GetUserUsername(ctx context.Context, userID int64) (username string, found bool, err error) {
|
||||
err = s.db.QueryRow(ctx, getUserUsernameQuery, s.telegramUserID, userID).Scan(&username)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return "", false, nil
|
||||
}
|
||||
return username, err == nil, err
|
||||
}
|
||||
|
||||
func (s *ScopedStore) SetUserUsername(ctx context.Context, userID int64, username string) (err error) {
|
||||
_, err = s.db.Exec(ctx, setUserUsernameQuery, s.telegramUserID, userID, username)
|
||||
return
|
||||
}
|
||||
|
||||
func (s *ScopedStore) GetUserMetadata(ctx context.Context, userID int64) (username string, accessHash int64, found bool, err error) {
|
||||
err = s.db.QueryRow(ctx, getUserMetadataQuery, s.telegramUserID, userID).Scan(&username, &accessHash)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return "", 0, false, nil
|
||||
}
|
||||
return username, accessHash, err == nil, err
|
||||
}
|
||||
|
||||
func (s *ScopedStore) SetUserMetadata(ctx context.Context, userID int64, username string, accessHash int64) (err error) {
|
||||
_, err = s.db.Exec(ctx, setUserMetadataQuery, s.telegramUserID, userID, username, accessHash)
|
||||
return
|
||||
}
|
||||
|
||||
// Helper Functions
|
||||
|
||||
func (s *ScopedStore) assertUserIDMatches(userID int64) {
|
||||
|
||||
@@ -31,6 +31,16 @@ CREATE TABLE telegram_channel_access_hashes (
|
||||
PRIMARY KEY (user_id, channel_id)
|
||||
);
|
||||
|
||||
CREATE TABLE telegram_user_metadata (
|
||||
receiver_id INTEGER,
|
||||
user_id INTEGER,
|
||||
|
||||
access_hash INTEGER NOT NULL,
|
||||
username TEXT,
|
||||
|
||||
PRIMARY KEY (receiver_id, user_id)
|
||||
);
|
||||
|
||||
CREATE TABLE telegram_file (
|
||||
id TEXT PRIMARY KEY,
|
||||
mxc TEXT NOT NULL,
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
-- v3: Move the user access hash to a table so it can be per-user
|
||||
|
||||
CREATE TABLE telegram_user_metadata (
|
||||
receiver_id INTEGER,
|
||||
user_id INTEGER,
|
||||
|
||||
access_hash INTEGER NOT NULL,
|
||||
username TEXT,
|
||||
|
||||
PRIMARY KEY (receiver_id, user_id)
|
||||
);
|
||||
|
||||
INSERT INTO telegram_user_metadata (receiver_id, user_id, access_hash, username)
|
||||
SELECT ul.id, g.id, g.metadata->>'access_hash', g.metadata->>'username'
|
||||
FROM user_login ul, ghost g;
|
||||
@@ -235,7 +235,7 @@ func (t *TelegramClient) updateGhost(ctx context.Context, userID int64, user *tg
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
userInfo, err := t.getUserInfoFromTelegramUser(user)
|
||||
userInfo, err := t.getUserInfoFromTelegramUser(ctx, user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -468,10 +468,12 @@ func (t *TelegramClient) inputPeerForPortalID(ctx context.Context, portalID netw
|
||||
}
|
||||
switch peerType {
|
||||
case ids.PeerTypeUser:
|
||||
if ghost, err := t.main.Bridge.DB.Ghost.GetByID(ctx, ids.MakeUserID(id)); err != nil {
|
||||
return nil, err
|
||||
if accessHash, found, err := t.ScopedStore.GetUserAccessHash(ctx, id); err != nil {
|
||||
return nil, fmt.Errorf("failed to get user access hash for %d: %w", id, err)
|
||||
} else if !found {
|
||||
return nil, fmt.Errorf("user access hash not found for %d", id)
|
||||
} else {
|
||||
return &tg.InputPeerUser{UserID: id, AccessHash: ghost.Metadata.(*GhostMetadata).AccessHash}, nil
|
||||
return &tg.InputPeerUser{UserID: id, AccessHash: accessHash}, nil
|
||||
}
|
||||
case ids.PeerTypeChat:
|
||||
return &tg.InputPeerChat{ChatID: id}, nil
|
||||
|
||||
Reference in New Issue
Block a user