move gotd fork into repo. (#111)
- update to latest telegram layer - remove some references to fields in tg.Entities that don't exist in the schema - originally added here: https://github.com/beeper/td/commit/820929062a2ba0104397bc01235ab58a9cff780e - referenced here - https://github.com/mautrix/telegramgo/commit/124f0967ed195b5a380c9bd02e170ada9710dde3 - https://github.com/mautrix/telegramgo/commit/4205047aab2e0639217148b5d125bfaab668bd8e
This commit is contained in:
@@ -0,0 +1,254 @@
|
||||
// Package dialogs contains dialog iteration helper.
|
||||
package dialogs
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/go-faster/errors"
|
||||
|
||||
"go.mau.fi/mautrix-telegram/pkg/gotd/telegram/message/peer"
|
||||
"go.mau.fi/mautrix-telegram/pkg/gotd/tg"
|
||||
)
|
||||
|
||||
// Elem is a dialog iterator element.
|
||||
type Elem struct {
|
||||
Dialog tg.DialogClass
|
||||
Peer tg.InputPeerClass
|
||||
Last tg.NotEmptyMessage
|
||||
Entities peer.Entities
|
||||
}
|
||||
|
||||
// Iterator is a dialog stream iterator.
|
||||
type Iterator struct {
|
||||
// Current state.
|
||||
lastErr error
|
||||
// Buffer state.
|
||||
buf []Elem
|
||||
bufCur int
|
||||
// Request state.
|
||||
limit int
|
||||
lastBatch bool
|
||||
// Offset parameters state.
|
||||
offsetID int
|
||||
offsetDate int
|
||||
offsetPeer tg.InputPeerClass
|
||||
// Remote state.
|
||||
count int
|
||||
totalGot bool
|
||||
|
||||
// Query builder.
|
||||
query Query
|
||||
}
|
||||
|
||||
// NewIterator creates new iterator.
|
||||
func NewIterator(query Query, limit int) *Iterator {
|
||||
return &Iterator{
|
||||
buf: make([]Elem, 0, limit),
|
||||
bufCur: -1,
|
||||
limit: limit,
|
||||
query: query,
|
||||
offsetPeer: &tg.InputPeerEmpty{},
|
||||
}
|
||||
}
|
||||
|
||||
// OffsetID sets OffsetID request parameter.
|
||||
func (m *Iterator) OffsetID(offsetID int) *Iterator {
|
||||
m.offsetID = offsetID
|
||||
return m
|
||||
}
|
||||
|
||||
// OffsetDate sets OffsetDate request parameter.
|
||||
func (m *Iterator) OffsetDate(offsetDate int) *Iterator {
|
||||
m.offsetDate = offsetDate
|
||||
return m
|
||||
}
|
||||
|
||||
// OffsetPeer sets OffsetPeer request parameter.
|
||||
func (m *Iterator) OffsetPeer(offsetPeer tg.InputPeerClass) *Iterator {
|
||||
m.offsetPeer = offsetPeer
|
||||
return m
|
||||
}
|
||||
|
||||
// messageMap is a helper to store messages for multiple peers.
|
||||
type messageMap map[DialogKey]tg.NotEmptyMessage
|
||||
|
||||
func (m messageMap) collect(messages tg.MessageClassArray) error {
|
||||
for _, msg := range messages {
|
||||
nonEmpty, ok := msg.AsNotEmpty()
|
||||
if !ok {
|
||||
// TODO(tdakkota): Maybe should I return error here?
|
||||
continue
|
||||
}
|
||||
|
||||
var key DialogKey
|
||||
if err := key.FromPeer(nonEmpty.GetPeerID()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m[key] = nonEmpty
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Iterator) apply(r tg.MessagesDialogsClass) error {
|
||||
if m.lastBatch {
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
messages tg.MessageClassArray
|
||||
dialogs tg.DialogClassArray
|
||||
entities peer.Entities
|
||||
)
|
||||
|
||||
switch dlgs := r.(type) {
|
||||
case *tg.MessagesDialogs: // messages.dialogs#15ba6c40
|
||||
dialogs = dlgs.Dialogs
|
||||
messages = dlgs.Messages
|
||||
entities = peer.EntitiesFromResult(dlgs)
|
||||
|
||||
m.count = len(messages)
|
||||
m.lastBatch = true
|
||||
case *tg.MessagesDialogsSlice: // messages.dialogsSlice#71e094f3
|
||||
dialogs = dlgs.Dialogs
|
||||
messages = dlgs.Messages
|
||||
entities = peer.EntitiesFromResult(dlgs)
|
||||
|
||||
m.count = dlgs.Count
|
||||
m.lastBatch = len(dlgs.Dialogs) == 0
|
||||
default: // messages.dialogsNotModified#f0e3e596
|
||||
return errors.Errorf("unexpected type %T", r)
|
||||
}
|
||||
m.totalGot = true
|
||||
|
||||
msgMap := make(messageMap, len(messages))
|
||||
if err := msgMap.collect(messages); err != nil {
|
||||
return errors.Wrap(err, "collect last messages")
|
||||
}
|
||||
|
||||
m.bufCur = -1
|
||||
m.buf = m.buf[:0]
|
||||
|
||||
var last tg.NotEmptyMessage
|
||||
for _, dlg := range dialogs {
|
||||
var key DialogKey
|
||||
if err := key.FromPeer(dlg.GetPeer()); err == nil {
|
||||
last = msgMap[key]
|
||||
}
|
||||
|
||||
p, err := entities.ExtractPeer(dlg.GetPeer())
|
||||
if err != nil {
|
||||
p = &tg.InputPeerEmpty{}
|
||||
}
|
||||
|
||||
m.buf = append(m.buf, Elem{
|
||||
Dialog: dlg,
|
||||
Peer: p,
|
||||
Last: last,
|
||||
Entities: entities,
|
||||
})
|
||||
}
|
||||
|
||||
if !m.lastBatch && len(m.buf) > 0 {
|
||||
if last != nil {
|
||||
m.offsetID = last.GetID()
|
||||
m.offsetDate = last.GetDate()
|
||||
}
|
||||
|
||||
p, err := entities.ExtractPeer(dialogs[len(m.buf)-1].GetPeer())
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "get offset peer")
|
||||
}
|
||||
m.offsetPeer = p
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Iterator) requestNext(ctx context.Context) error {
|
||||
r, err := m.query.Query(ctx, Request{
|
||||
OffsetID: m.offsetID,
|
||||
OffsetDate: m.offsetDate,
|
||||
OffsetPeer: m.offsetPeer,
|
||||
Limit: m.limit,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return m.apply(r)
|
||||
}
|
||||
|
||||
func (m *Iterator) bufNext() bool {
|
||||
if len(m.buf)-1 <= m.bufCur {
|
||||
return false
|
||||
}
|
||||
|
||||
m.bufCur++
|
||||
return true
|
||||
}
|
||||
|
||||
// Total returns last fetched count of elements.
|
||||
// If count was not fetched before, it requests server using FetchTotal.
|
||||
func (m *Iterator) Total(ctx context.Context) (int, error) {
|
||||
if m.totalGot {
|
||||
return m.count, nil
|
||||
}
|
||||
|
||||
return m.FetchTotal(ctx)
|
||||
}
|
||||
|
||||
// FetchTotal fetches and returns count of elements.
|
||||
func (m *Iterator) FetchTotal(ctx context.Context) (int, error) {
|
||||
r, err := m.query.Query(ctx, Request{
|
||||
Limit: 1,
|
||||
OffsetPeer: &tg.InputPeerEmpty{},
|
||||
})
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "fetch total")
|
||||
}
|
||||
|
||||
switch dlgs := r.(type) {
|
||||
case *tg.MessagesDialogs: // messages.dialogs#15ba6c40
|
||||
m.count = len(dlgs.Dialogs)
|
||||
case *tg.MessagesDialogsSlice: // messages.dialogsSlice#71e094f3
|
||||
m.count = dlgs.Count
|
||||
default: // messages.dialogsNotModified#f0e3e596
|
||||
return 0, errors.Errorf("unexpected type %T", r)
|
||||
}
|
||||
|
||||
m.totalGot = true
|
||||
return m.count, nil
|
||||
}
|
||||
|
||||
// Next prepares the next message for reading with the Value method.
|
||||
// It returns true on success, or false if there is no next message or an error happened while preparing it.
|
||||
// Err should be consulted to distinguish between the two cases.
|
||||
func (m *Iterator) Next(ctx context.Context) bool {
|
||||
if m.lastErr != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if !m.bufNext() {
|
||||
// If buffer is empty, we should fetch next batch.
|
||||
if err := m.requestNext(ctx); err != nil {
|
||||
m.lastErr = err
|
||||
return false
|
||||
}
|
||||
// Try again with new buffer.
|
||||
return m.bufNext()
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Value returns current message.
|
||||
func (m *Iterator) Value() Elem {
|
||||
return m.buf[m.bufCur]
|
||||
}
|
||||
|
||||
// Err returns the error, if any, that was encountered during iteration.
|
||||
func (m *Iterator) Err() error {
|
||||
return m.lastErr
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package dialogs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"go.mau.fi/mautrix-telegram/pkg/gotd/tg"
|
||||
"go.mau.fi/mautrix-telegram/pkg/gotd/tgmock"
|
||||
)
|
||||
|
||||
func generateDialogs(count int) []tg.DialogClass {
|
||||
r := make([]tg.DialogClass, 0, count)
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
r = append(r, &tg.Dialog{
|
||||
Peer: &tg.PeerChannel{ChannelID: int64(i)},
|
||||
})
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func result(r []tg.DialogClass, count int) tg.MessagesDialogsClass {
|
||||
msgs := make([]tg.MessageClass, 0, len(r))
|
||||
for i, dlg := range r {
|
||||
msgs = append(msgs, &tg.Message{
|
||||
ID: i,
|
||||
PeerID: dlg.GetPeer(),
|
||||
})
|
||||
}
|
||||
|
||||
chats := make([]tg.ChatClass, 0, len(r))
|
||||
for i, dlg := range r {
|
||||
id := dlg.GetPeer().(*tg.PeerChannel).ChannelID
|
||||
chats = append(chats, &tg.Channel{
|
||||
ID: id,
|
||||
AccessHash: 10,
|
||||
Photo: &tg.ChatPhoto{
|
||||
PhotoID: int64(i),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return &tg.MessagesDialogsSlice{
|
||||
Dialogs: r,
|
||||
Messages: msgs,
|
||||
Chats: chats,
|
||||
Count: count,
|
||||
}
|
||||
}
|
||||
|
||||
func TestIterator(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
mock := tgmock.NewRequire(t)
|
||||
limit := 10
|
||||
totalRows := 3 * limit
|
||||
expected := generateDialogs(totalRows)
|
||||
raw := tg.NewClient(mock)
|
||||
|
||||
mock.Expect().ThenResult(result(expected[0:limit], totalRows))
|
||||
mock.Expect().ThenResult(result(expected[limit:2*limit], totalRows))
|
||||
mock.Expect().ThenResult(result(expected[2*limit:3*limit], totalRows))
|
||||
mock.Expect().ThenResult(result(expected[3*limit:], totalRows))
|
||||
|
||||
iter := NewQueryBuilder(raw).GetDialogs().BatchSize(10).Iter()
|
||||
i := 0
|
||||
for iter.Next(ctx) {
|
||||
require.Equal(t, expected[i].GetPeer(), iter.Value().Dialog.GetPeer())
|
||||
i++
|
||||
}
|
||||
require.NoError(t, iter.Err())
|
||||
require.Equal(t, totalRows, i)
|
||||
|
||||
total, err := iter.Total(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, totalRows, total)
|
||||
|
||||
mock.ExpectCall(&tg.MessagesGetDialogsRequest{
|
||||
OffsetPeer: &tg.InputPeerEmpty{},
|
||||
Limit: 1,
|
||||
}).ThenResult(result(expected[:0], totalRows))
|
||||
total, err = iter.FetchTotal(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, totalRows, total)
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package dialogs
|
||||
|
||||
import (
|
||||
"github.com/go-faster/errors"
|
||||
|
||||
"go.mau.fi/mautrix-telegram/pkg/gotd/tg"
|
||||
)
|
||||
|
||||
// PeerKind represents peer kind.
|
||||
type PeerKind int
|
||||
|
||||
const (
|
||||
// User is a private chat with user.
|
||||
User PeerKind = iota
|
||||
// Chat is a legacy chat.
|
||||
Chat
|
||||
// Channel is a supergroup/channel.
|
||||
Channel
|
||||
)
|
||||
|
||||
// DialogKey is a generic peer key.
|
||||
type DialogKey struct {
|
||||
Kind PeerKind
|
||||
ID int64
|
||||
AccessHash int64
|
||||
}
|
||||
|
||||
// FromInputPeer fills key using given peer.
|
||||
func (d *DialogKey) FromInputPeer(peer tg.InputPeerClass) error {
|
||||
switch v := peer.(type) {
|
||||
case *tg.InputPeerUser:
|
||||
d.Kind = User
|
||||
d.ID = v.UserID
|
||||
d.AccessHash = v.AccessHash
|
||||
case *tg.InputPeerChat:
|
||||
d.Kind = Chat
|
||||
d.ID = v.ChatID
|
||||
case *tg.InputPeerChannel:
|
||||
d.Kind = Channel
|
||||
d.ID = v.ChannelID
|
||||
d.AccessHash = v.AccessHash
|
||||
default:
|
||||
return errors.Errorf("unexpected type %T", peer)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// FromPeer fills key using given peer.
|
||||
func (d *DialogKey) FromPeer(peer tg.PeerClass) error {
|
||||
switch v := peer.(type) {
|
||||
case *tg.PeerUser:
|
||||
d.Kind = User
|
||||
d.ID = v.UserID
|
||||
case *tg.PeerChat:
|
||||
d.Kind = Chat
|
||||
d.ID = v.ChatID
|
||||
case *tg.PeerChannel:
|
||||
d.Kind = Channel
|
||||
d.ID = v.ChannelID
|
||||
default:
|
||||
return errors.Errorf("unexpected type %T", peer)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
// Code generated by itergen, DO NOT EDIT.
|
||||
|
||||
package dialogs
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/go-faster/errors"
|
||||
|
||||
"go.mau.fi/mautrix-telegram/pkg/gotd/tg"
|
||||
)
|
||||
|
||||
// No-op definition for keeping imports.
|
||||
var _ = context.Background()
|
||||
|
||||
// Request is a parameter for Query.
|
||||
type Request struct {
|
||||
OffsetDate int
|
||||
OffsetID int
|
||||
OffsetPeer tg.InputPeerClass
|
||||
Limit int
|
||||
}
|
||||
|
||||
// Query is an abstraction for dialogs request.
|
||||
// NB: iterator mutates returned data (sorts, at least).
|
||||
type Query interface {
|
||||
Query(ctx context.Context, req Request) (tg.MessagesDialogsClass, error)
|
||||
}
|
||||
|
||||
// QueryFunc is a function adapter for Query.
|
||||
type QueryFunc func(ctx context.Context, req Request) (tg.MessagesDialogsClass, error)
|
||||
|
||||
// Query implements Query interface.
|
||||
func (q QueryFunc) Query(ctx context.Context, req Request) (tg.MessagesDialogsClass, error) {
|
||||
return q(ctx, req)
|
||||
}
|
||||
|
||||
// QueryBuilder is a helper to create message queries.
|
||||
type QueryBuilder struct {
|
||||
raw *tg.Client
|
||||
}
|
||||
|
||||
// NewQueryBuilder creates new QueryBuilder.
|
||||
func NewQueryBuilder(raw *tg.Client) *QueryBuilder {
|
||||
return &QueryBuilder{raw: raw}
|
||||
}
|
||||
|
||||
// GetDialogsQueryBuilder is query builder of MessagesGetDialogs.
|
||||
type GetDialogsQueryBuilder struct {
|
||||
raw *tg.Client
|
||||
req tg.MessagesGetDialogsRequest
|
||||
batchSize int
|
||||
offsetDate int
|
||||
offsetID int
|
||||
offsetPeer tg.InputPeerClass
|
||||
}
|
||||
|
||||
// GetDialogs creates query builder of MessagesGetDialogs.
|
||||
func (q *QueryBuilder) GetDialogs() *GetDialogsQueryBuilder {
|
||||
b := &GetDialogsQueryBuilder{
|
||||
raw: q.raw,
|
||||
batchSize: 1,
|
||||
req: tg.MessagesGetDialogsRequest{},
|
||||
}
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
// BatchSize sets buffer of message loaded from one request.
|
||||
// Be carefully, when set this limit, because Telegram does not return error if limit is too big,
|
||||
// so results can be incorrect.
|
||||
func (b *GetDialogsQueryBuilder) BatchSize(batchSize int) *GetDialogsQueryBuilder {
|
||||
b.batchSize = batchSize
|
||||
return b
|
||||
}
|
||||
|
||||
// OffsetDate sets offsetDate from which iterate start.
|
||||
func (b *GetDialogsQueryBuilder) OffsetDate(offsetDate int) *GetDialogsQueryBuilder {
|
||||
b.offsetDate = offsetDate
|
||||
return b
|
||||
}
|
||||
|
||||
// OffsetID sets offsetID from which iterate start.
|
||||
func (b *GetDialogsQueryBuilder) OffsetID(offsetID int) *GetDialogsQueryBuilder {
|
||||
b.offsetID = offsetID
|
||||
return b
|
||||
}
|
||||
|
||||
// FolderID sets FolderID field of GetDialogs query.
|
||||
func (b *GetDialogsQueryBuilder) FolderID(paramFolderID int) *GetDialogsQueryBuilder {
|
||||
b.req.FolderID = paramFolderID
|
||||
return b
|
||||
}
|
||||
|
||||
// Query implements Query interface.
|
||||
func (b *GetDialogsQueryBuilder) Query(ctx context.Context, req Request) (tg.MessagesDialogsClass, error) {
|
||||
r := &tg.MessagesGetDialogsRequest{
|
||||
Limit: req.Limit,
|
||||
}
|
||||
|
||||
r.FolderID = b.req.FolderID
|
||||
r.OffsetDate = req.OffsetDate
|
||||
r.OffsetID = req.OffsetID
|
||||
r.OffsetPeer = req.OffsetPeer
|
||||
return b.raw.MessagesGetDialogs(ctx, r)
|
||||
}
|
||||
|
||||
// Iter returns iterator using built query.
|
||||
func (b *GetDialogsQueryBuilder) Iter() *Iterator {
|
||||
iter := NewIterator(b, b.batchSize)
|
||||
iter = iter.OffsetDate(b.offsetDate)
|
||||
iter = iter.OffsetID(b.offsetID)
|
||||
return iter
|
||||
}
|
||||
|
||||
// ForEach calls given callback on each iterator element.
|
||||
func (b *GetDialogsQueryBuilder) ForEach(ctx context.Context, cb func(context.Context, Elem) error) error {
|
||||
iter := b.Iter()
|
||||
for iter.Next(ctx) {
|
||||
if err := cb(ctx, iter.Value()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return iter.Err()
|
||||
}
|
||||
|
||||
// Count fetches remote state to get number of elements.
|
||||
func (b *GetDialogsQueryBuilder) Count(ctx context.Context) (int, error) {
|
||||
iter := b.Iter()
|
||||
c, err := iter.Total(ctx)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "get total")
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// Collect creates iterator and collects all elements to slice.
|
||||
func (b *GetDialogsQueryBuilder) Collect(ctx context.Context) ([]Elem, error) {
|
||||
iter := b.Iter()
|
||||
c, err := iter.Total(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "get total")
|
||||
}
|
||||
|
||||
r := make([]Elem, 0, c)
|
||||
for iter.Next(ctx) {
|
||||
r = append(r, iter.Value())
|
||||
}
|
||||
|
||||
return r, iter.Err()
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package dialogs
|
||||
|
||||
//go:generate go run go.mau.fi/mautrix-telegram/pkg/gotd/telegram/query/internal/itergen -result=MessagesDialogsClass -package=dialogs -out=queries.gen.go
|
||||
@@ -0,0 +1,60 @@
|
||||
package dialogs
|
||||
|
||||
import (
|
||||
"go.mau.fi/mautrix-telegram/pkg/gotd/telegram/message/peer"
|
||||
"go.mau.fi/mautrix-telegram/pkg/gotd/telegram/query/channels/participants"
|
||||
"go.mau.fi/mautrix-telegram/pkg/gotd/telegram/query/messages"
|
||||
"go.mau.fi/mautrix-telegram/pkg/gotd/telegram/query/photos"
|
||||
"go.mau.fi/mautrix-telegram/pkg/gotd/tg"
|
||||
)
|
||||
|
||||
// Messages returns new messages history query builder for current dialog.
|
||||
func (e Elem) Messages(raw *tg.Client) *messages.GetHistoryQueryBuilder {
|
||||
return messages.NewQueryBuilder(raw).GetHistory(e.Peer)
|
||||
}
|
||||
|
||||
// Search returns new search query builder for current dialog.
|
||||
func (e Elem) Search(raw *tg.Client) *messages.SearchQueryBuilder {
|
||||
return messages.NewQueryBuilder(raw).Search(e.Peer)
|
||||
}
|
||||
|
||||
// Replies returns new replies query builder for current dialog.
|
||||
func (e Elem) Replies(raw *tg.Client) *messages.GetRepliesQueryBuilder {
|
||||
return messages.NewQueryBuilder(raw).GetReplies(e.Peer)
|
||||
}
|
||||
|
||||
// UnreadMentions returns new unread mentions query builder for current dialog.
|
||||
func (e Elem) UnreadMentions(raw *tg.Client) *messages.GetUnreadMentionsQueryBuilder {
|
||||
return messages.NewQueryBuilder(raw).GetUnreadMentions(e.Peer)
|
||||
}
|
||||
|
||||
// RecentLocations returns new live location history query builder for current dialog.
|
||||
func (e Elem) RecentLocations(raw *tg.Client) *messages.GetRecentLocationsQueryBuilder {
|
||||
return messages.NewQueryBuilder(raw).GetRecentLocations(e.Peer)
|
||||
}
|
||||
|
||||
// UserPhotos returns new user photo query builder for current dialog.
|
||||
// If peer is not user, returns false.
|
||||
func (e Elem) UserPhotos(raw *tg.Client) (*photos.GetUserPhotosQueryBuilder, bool) {
|
||||
user, ok := peer.ToInputUser(e.Peer)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
return photos.NewQueryBuilder(raw).GetUserPhotos(user), true
|
||||
}
|
||||
|
||||
// Participants returns new channel participants query builder for current dialog.
|
||||
// If peer is not channel, returns false.
|
||||
func (e Elem) Participants(raw *tg.Client) (*participants.GetParticipantsQueryBuilder, bool) {
|
||||
channel, ok := peer.ToInputChannel(e.Peer)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
return participants.NewQueryBuilder(raw).GetParticipants(channel), true
|
||||
}
|
||||
|
||||
// Deleted denotes that dialog is deleted.
|
||||
func (e Elem) Deleted() bool {
|
||||
_, ok := e.Peer.(*tg.InputPeerEmpty)
|
||||
return ok
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package dialogs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"go.mau.fi/mautrix-telegram/pkg/gotd/tg"
|
||||
"go.mau.fi/mautrix-telegram/pkg/gotd/tgerr"
|
||||
"go.mau.fi/mautrix-telegram/pkg/gotd/tgmock"
|
||||
)
|
||||
|
||||
func TestElem(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
mock := tgmock.NewRequire(t)
|
||||
raw := tg.NewClient(mock)
|
||||
|
||||
ch := Elem{
|
||||
Peer: &tg.InputPeerChannel{},
|
||||
}
|
||||
testErr := tgerr.New(1337, "TEST_ERROR")
|
||||
|
||||
var err error
|
||||
mock.Expect().ThenRPCErr(testErr)
|
||||
_, err = ch.Messages(raw).Count(ctx)
|
||||
require.Error(t, err)
|
||||
mock.Expect().ThenRPCErr(testErr)
|
||||
_, err = ch.Search(raw).Count(ctx)
|
||||
require.Error(t, err)
|
||||
mock.Expect().ThenRPCErr(testErr)
|
||||
_, err = ch.Replies(raw).Count(ctx)
|
||||
require.Error(t, err)
|
||||
mock.Expect().ThenRPCErr(testErr)
|
||||
_, err = ch.UnreadMentions(raw).Count(ctx)
|
||||
require.Error(t, err)
|
||||
mock.Expect().ThenRPCErr(testErr)
|
||||
_, err = ch.RecentLocations(raw).Count(ctx)
|
||||
require.Error(t, err)
|
||||
|
||||
_, ok := ch.Participants(raw)
|
||||
require.True(t, ok)
|
||||
_, ok = ch.UserPhotos(raw)
|
||||
require.False(t, ok)
|
||||
|
||||
ch = Elem{
|
||||
Peer: &tg.InputPeerUser{},
|
||||
}
|
||||
|
||||
_, ok = ch.Participants(raw)
|
||||
require.False(t, ok)
|
||||
_, ok = ch.UserPhotos(raw)
|
||||
require.True(t, ok)
|
||||
}
|
||||
Reference in New Issue
Block a user