Skip to content

Commit

Permalink
Merge pull request #688 from tdakkota/feat/admin-helpers
Browse files Browse the repository at this point in the history
feat(peers): add admin helpers
  • Loading branch information
ernado committed Mar 10, 2022
2 parents 4cedf9a + d171365 commit 1dfed8b
Show file tree
Hide file tree
Showing 26 changed files with 1,777 additions and 114 deletions.
45 changes: 23 additions & 22 deletions telegram/peers/channel.go
Expand Up @@ -100,6 +100,11 @@ func (c Channel) Sync(ctx context.Context) error {
return nil
}

// Manager returns attached Manager.
func (c Channel) Manager() *Manager {
return c.m
}

// Report reports a peer for violation of telegram's Terms of Service.
func (c Channel) Report(ctx context.Context, reason tg.ReportReasonClass, message string) error {
if _, err := c.m.api.AccountReportPeer(ctx, &tg.AccountReportPeerRequest{
Expand Down Expand Up @@ -130,24 +135,34 @@ func (c Channel) FullRaw(ctx context.Context) (*tg.ChannelFull, error) {

// ToBroadcast tries to convert this Channel to Broadcast.
func (c Channel) ToBroadcast() (Broadcast, bool) {
if !c.raw.Broadcast {
if !c.IsBroadcast() {
return Broadcast{}, false
}
return Broadcast{
Channel: c,
}, true
}

// IsBroadcast whether this Channel is Broadcast.
func (c Channel) IsBroadcast() bool {
return c.raw.Broadcast
}

// ToSupergroup tries to convert this Channel to Supergroup.
func (c Channel) ToSupergroup() (Supergroup, bool) {
if !c.raw.Megagroup {
if !c.IsSupergroup() {
return Supergroup{}, false
}
return Supergroup{
Channel: c,
}, true
}

// IsSupergroup whether this Channel is Supergroup.
func (c Channel) IsSupergroup() bool {
return c.raw.Megagroup
}

// InviteLinks returns InviteLinks for this peer.
func (c Channel) InviteLinks() InviteLinks {
return InviteLinks{
Expand Down Expand Up @@ -203,20 +218,23 @@ func (c Channel) NoForwards() bool {
//
// See https://core.telegram.org/api/rights.
func (c Channel) AdminRights() (tg.ChatAdminRights, bool) {
// TODO(tdakkota): add wrapper for raw object?
return c.raw.GetAdminRights()
}

// BannedRights returns banned rights of the user in this channel.
//
// See https://core.telegram.org/api/rights.
func (c Channel) BannedRights() (tg.ChatBannedRights, bool) {
// TODO(tdakkota): add wrapper for raw object?
return c.raw.GetBannedRights()
}

// DefaultBannedRights returns default chat rights.
//
// See https://core.telegram.org/api/rights.
func (c Channel) DefaultBannedRights() (tg.ChatBannedRights, bool) {
// TODO(tdakkota): add wrapper for raw object?
return c.raw.GetDefaultBannedRights()
}

Expand Down Expand Up @@ -263,36 +281,19 @@ func (c Channel) SetTitle(ctx context.Context, title string) error {

// SetDescription sets new description for this Chat.
func (c Channel) SetDescription(ctx context.Context, about string) error {
if _, err := c.m.api.MessagesEditChatAbout(ctx, &tg.MessagesEditChatAboutRequest{
Peer: c.InputPeer(),
About: about,
}); err != nil {
return errors.Wrap(err, "edit channel about")
}
return nil
return c.m.editAbout(ctx, c.InputPeer(), about)
}

// SetReactions sets list of available reactions.
//
// Empty list disables reactions at all.
func (c Channel) SetReactions(ctx context.Context, reactions ...string) error {
return c.setReactions(ctx, reactions...)
return c.m.editReactions(ctx, c.InputPeer(), reactions...)
}

// DisableReactions disables reactions.
func (c Channel) DisableReactions(ctx context.Context) error {
return c.setReactions(ctx)
}

func (c Channel) setReactions(ctx context.Context, reactions ...string) error {
if _, err := c.m.api.MessagesSetChatAvailableReactions(ctx, &tg.MessagesSetChatAvailableReactionsRequest{
Peer: c.InputPeer(),
AvailableReactions: reactions,
}); err != nil {
return errors.Wrap(err, "set reactions")
}

return nil
return c.m.editReactions(ctx, c.InputPeer())
}

// TODO(tdakkota): add more getters, helpers and convertors
54 changes: 54 additions & 0 deletions telegram/peers/channel_test.go
Expand Up @@ -73,6 +73,24 @@ func TestChannelGetters(t *testing.T) {
a.Equal(b.raw.Broadcast, ok)
a.Equal(b.raw.Signatures, b.Signatures())
}
{
v, ok := u.AdminRights()
v2, ok2 := u.raw.GetAdminRights()
a.Equal(ok, ok2)
a.Equal(v2, v)
}
{
v, ok := u.BannedRights()
v2, ok2 := u.raw.GetBannedRights()
a.Equal(ok, ok2)
a.Equal(v2, v)
}
{
v, ok := u.DefaultBannedRights()
v2, ok2 := u.raw.GetDefaultBannedRights()
a.Equal(ok2, ok)
a.Equal(v2, v)
}
}

func TestChannel_Leave(t *testing.T) {
Expand Down Expand Up @@ -134,3 +152,39 @@ func TestChannel_SetDescription(t *testing.T) {
}).ThenTrue()
a.NoError(ch.SetDescription(ctx, about))
}

func TestChannel_Join(t *testing.T) {
a := require.New(t)
ctx := context.Background()
mock, m := testManager(t)

ch := m.Channel(getTestChannel())

mock.ExpectCall(&tg.ChannelsJoinChannelRequest{
Channel: ch.InputChannel(),
}).ThenRPCErr(getTestError())
a.Error(ch.Join(ctx))

mock.ExpectCall(&tg.ChannelsJoinChannelRequest{
Channel: ch.InputChannel(),
}).ThenResult(&tg.Updates{})
a.NoError(ch.Join(ctx))
}

func TestChannel_Delete(t *testing.T) {
a := require.New(t)
ctx := context.Background()
mock, m := testManager(t)

ch := m.Channel(getTestChannel())

mock.ExpectCall(&tg.ChannelsDeleteChannelRequest{
Channel: ch.InputChannel(),
}).ThenRPCErr(getTestError())
a.Error(ch.Delete(ctx))

mock.ExpectCall(&tg.ChannelsDeleteChannelRequest{
Channel: ch.InputChannel(),
}).ThenResult(&tg.Updates{})
a.NoError(ch.Delete(ctx))
}
74 changes: 41 additions & 33 deletions telegram/peers/chat.go
Expand Up @@ -96,6 +96,11 @@ func (c Chat) Sync(ctx context.Context) error {
return nil
}

// Manager returns attached Manager.
func (c Chat) Manager() *Manager {
return c.m
}

// Report reports a peer for violation of telegram's Terms of Service.
func (c Chat) Report(ctx context.Context, reason tg.ReportReasonClass, message string) error {
if _, err := c.m.api.AccountReportPeer(ctx, &tg.AccountReportPeerRequest{
Expand Down Expand Up @@ -139,12 +144,22 @@ func (c Chat) InviteLinks() InviteLinks {

// ToBroadcast tries to convert this Chat to Broadcast.
func (c Chat) ToBroadcast() (Broadcast, bool) {
return Broadcast{}, false
return Broadcast{}, c.IsBroadcast()
}

// IsBroadcast whether this Chat is Broadcast.
func (c Chat) IsBroadcast() bool {
return false
}

// ToSupergroup tries to convert this Chat to Supergroup.
func (c Chat) ToSupergroup() (Supergroup, bool) {
return Supergroup{}, false
return Supergroup{}, c.IsSupergroup()
}

// IsSupergroup whether this Chat is Supergroup.
func (c Chat) IsSupergroup() bool {
return false
}

// Creator whether the current user is the creator of this group.
Expand Down Expand Up @@ -196,13 +211,15 @@ func (c Chat) ParticipantsCount() int {
//
// See https://core.telegram.org/api/rights.
func (c Chat) AdminRights() (tg.ChatAdminRights, bool) {
// TODO(tdakkota): add wrapper for raw object?
return c.raw.GetAdminRights()
}

// DefaultBannedRights returns default chat rights.
//
// See https://core.telegram.org/api/rights.
func (c Chat) DefaultBannedRights() (tg.ChatBannedRights, bool) {
// TODO(tdakkota): add wrapper for raw object?
return c.raw.GetDefaultBannedRights()
}

Expand Down Expand Up @@ -240,51 +257,42 @@ func (c Chat) SetTitle(ctx context.Context, title string) error {

// SetDescription sets new description for this Chat.
func (c Chat) SetDescription(ctx context.Context, about string) error {
if _, err := c.m.api.MessagesEditChatAbout(ctx, &tg.MessagesEditChatAboutRequest{
Peer: c.InputPeer(),
About: about,
}); err != nil {
return errors.Wrap(err, "edit chat about")
}
return nil
}

// LeaveAndDelete leaves this chat and removes the entire chat history of this user in this chat.
func (c Chat) LeaveAndDelete(ctx context.Context) error {
return c.deleteMe(ctx, true)
}

func (c Chat) deleteMe(ctx context.Context, revokeHistory bool) error {
if _, err := c.m.api.MessagesDeleteChatUser(ctx, &tg.MessagesDeleteChatUserRequest{
RevokeHistory: revokeHistory,
ChatID: c.raw.GetID(),
UserID: &tg.InputUserSelf{},
}); err != nil {
return errors.Wrapf(err, "leave (revoke: %v)", revokeHistory)
}
return nil
return c.m.editAbout(ctx, c.InputPeer(), about)
}

// SetReactions sets list of available reactions.
//
// Empty list disables reactions at all.
func (c Chat) SetReactions(ctx context.Context, reactions ...string) error {
return c.setReactions(ctx, reactions...)
return c.m.editReactions(ctx, c.InputPeer(), reactions...)
}

// DisableReactions disables reactions.
func (c Chat) DisableReactions(ctx context.Context) error {
return c.setReactions(ctx)
return c.m.editReactions(ctx, c.InputPeer())
}

// LeaveAndDelete leaves this chat and removes the entire chat history of this user in this chat.
func (c Chat) LeaveAndDelete(ctx context.Context) error {
return c.deleteMe(ctx, true)
}

func (c Chat) deleteMe(ctx context.Context, revokeHistory bool) error {
return c.deleteUser(ctx, &tg.InputUserSelf{}, revokeHistory)
}

func (c Chat) setReactions(ctx context.Context, reactions ...string) error {
if _, err := c.m.api.MessagesSetChatAvailableReactions(ctx, &tg.MessagesSetChatAvailableReactionsRequest{
Peer: c.InputPeer(),
AvailableReactions: reactions,
func (c Chat) deleteUser(ctx context.Context, user tg.InputUserClass, revokeHistory bool) error {
if _, err := c.m.api.MessagesDeleteChatUser(ctx, &tg.MessagesDeleteChatUserRequest{
RevokeHistory: revokeHistory,
ChatID: c.raw.GetID(),
UserID: user,
}); err != nil {
return errors.Wrap(err, "set reactions")
_, self := user.(*tg.InputUserSelf)
if self {
return errors.Wrapf(err, "leave (revoke: %v)", revokeHistory)
}
return errors.Wrapf(err, "delete user (revoke: %v)", revokeHistory)
}

return nil
}

Expand Down
74 changes: 74 additions & 0 deletions telegram/peers/id.go
@@ -0,0 +1,74 @@
package peers

import (
"context"

"github.com/go-faster/errors"

"github.com/gotd/td/constant"
"github.com/gotd/td/tg"
"github.com/gotd/td/tgerr"
)

// ResolveTDLibID creates Peer using given constant.TDLibPeerID.
func (m *Manager) ResolveTDLibID(ctx context.Context, peerID constant.TDLibPeerID) (p Peer, err error) {
switch {
case peerID.IsUser():
p, err = m.ResolveUserID(ctx, peerID.ToPlain())
case peerID.IsChat():
p, err = m.ResolveChatID(ctx, peerID.ToPlain())
case peerID.IsChannel():
p, err = m.ResolveChannelID(ctx, peerID.ToPlain())
default:
return nil, errors.Errorf("invalid ID %d", peerID)
}
return p, err
}

// ResolveUserID creates User using given id.
func (m *Manager) ResolveUserID(ctx context.Context, id int64) (User, error) {
v, ok, err := m.storage.Find(ctx, Key{
Prefix: usersPrefix,
ID: id,
})
if err != nil {
return User{}, err
}
u, err := m.GetUser(ctx, &tg.InputUser{
UserID: id,
AccessHash: v.AccessHash,
})
if !ok && tgerr.Is(err, tg.ErrUserIDInvalid) {
return User{}, &PeerNotFoundError{
Peer: &tg.PeerUser{UserID: id},
}
}
return u, err
}

// ResolveChatID creates Chat using given id.
func (m *Manager) ResolveChatID(ctx context.Context, id int64) (Chat, error) {
c, err := m.GetChat(ctx, id)
return c, err
}

// ResolveChannelID creates Channel using given id.
func (m *Manager) ResolveChannelID(ctx context.Context, id int64) (Channel, error) {
v, ok, err := m.storage.Find(ctx, Key{
Prefix: channelPrefix,
ID: id,
})
if err != nil {
return Channel{}, err
}
c, err := m.GetChannel(ctx, &tg.InputChannel{
ChannelID: id,
AccessHash: v.AccessHash,
})
if !ok && tgerr.Is(err, tg.ErrChannelInvalid) {
return Channel{}, &PeerNotFoundError{
Peer: &tg.PeerChannel{ChannelID: id},
}
}
return c, err
}
5 changes: 5 additions & 0 deletions telegram/peers/manager.go
Expand Up @@ -39,3 +39,8 @@ func (m *Manager) Init(ctx context.Context) error {
}
return nil
}

// API returns used Client.
func (m *Manager) API() *tg.Client {
return m.api
}

0 comments on commit 1dfed8b

Please sign in to comment.