FILEREF_UPGRADE_NEEDED using GetFile function of TLSharp - c#

I'm trying to dowload a file from a conversation in telegram. I`m using TLSharp lib...
Please check my code:
var result = await client.GetContactsAsync();
var user = result.Users
.OfType<TLUser>()
.FirstOrDefault(x => x.Phone == "<phoneNumber>");
var inputPeer = new TLInputPeerUser() { UserId = user.Id };
var res = await client.SendRequestAsync<TLMessages>(new TLRequestGetHistory() { Peer = inputPeer });
var document = res.Messages
.OfType<TLMessage>()
.Where(m => m.Media != null)
.Select(m => m.Media)
.OfType<TLMessageMediaDocument>()
.Select(md => md.Document)
.OfType<TLDocument>()
.First();
var resFile = await client.GetFile(
new TLInputDocumentFileLocation()
{
AccessHash = document.AccessHash,
Id = document.Id,
Version = document.Version
},
(int)Math.Pow(2, Math.Ceiling(Math.Log(document.Size, 2))) * 4);
This code is getting this exception:
FILEREF_UPGRADE_NEEDED
Please, there are any way to get a file from an conversation without get this error?

TLSharp seems no longer maintained. You might want to switch to WTelegramClient which is similar but better.
Then you can use the helper method that simplify the download process:
using (var stream = File.Create(outputFilename))
await client.DownloadFileAsync(document, stream);

Related

Paging with CosmosClient in CosmosDB

I'm trying to implement paging using the SDK v3 CosmosClient instead of the old DocumentClient.
Reason for this is it seems DocumentClient doesn't translate LINQ queries that contains spatial functions very well (ie: When using Within() I'll get an error from DocumentClient stating the methods is not implemented).
Paging works well with DocumentClient.CreateDocumentQuery<T> as such:
var query = DocumentClient.CreateDocumentQuery<T>(UriFactory.CreateDocumentCollectionUri("master", "features"), feedOptions)
.Where(t => t.Type == typeof(T).Name)
.Where(pred)
.AsDocumentQuery();
string queryContinuationToken = null;
var page = await query.ExecuteNextAsync<T>();
if (query.HasMoreResults)
queryContinuationToken = page.ResponseContinuation;
I'm at a little loss as to where to gather a continuation token using CosmosClient and its Container class:
QueryRequestOptions options = new QueryRequestOptions();
options.MaxItemCount = maxRecords;
FeedIterator<T> feed;
if (continuationToken == "")
feed = Container.GetItemLinqQueryable<T>(true, null, options).Where(x => x.Type == typeof(T).Name).Where(pred).ToFeedIterator();
else
feed = Container.GetItemLinqQueryable<T>(true, continuationToken, options).Where(x => x.Type == typeof(T).Name).Where(pred).ToFeedIterator();
FeedIterator seems to have some of the members IDocumentQuery has (like HasMoreResults) but I can't find a continuation token anywhere.
What am I missing?
Alright, here's a Where method I implemented. Seems to work at first glance.
If you do var f = feed.ReadNextAsync() you won't get an object that's of type FeedResponse, preventing you access to the token. You need to declare f explicitly of type FeedResponse<T>
public async Task<(IEnumerable<T> Results, string ContinuationToken)> Where<T>(Expression<Func<T, bool>> pred, int maxRecords = 0, string partitionKey = "", string continuationToken = "") where T : IDocumentModel
{
QueryRequestOptions options = new QueryRequestOptions();
if (partitionKey != "")
options.PartitionKey = new PartitionKey(partitionKey);
if (maxRecords == 0)
{
return (Container.GetItemLinqQueryable<T>(true, null, options).Where(x => x.Type == typeof(T).Name).Where(pred), "");
}
else
{
options.MaxItemCount = maxRecords;
string token = "";
FeedIterator<T> feed;
List<T> res = new List<T>();
if (continuationToken == "")
feed = Container.GetItemLinqQueryable<T>(true, null, options).Where(x => x.Type == typeof(T).Name).Where(pred).ToFeedIterator();
else
feed = Container.GetItemLinqQueryable<T>(true, continuationToken, options).Where(x => x.Type == typeof(T).Name).Where(pred).ToFeedIterator();
Microsoft.Azure.Cosmos.FeedResponse<T> f = await feed.ReadNextAsync();
token = f.ContinuationToken;
foreach (var item in f)
{
res.Add(item);
}
return (res, token);
}
}
With the version 3.12.0 of the Cosmos SDK the following works as expected as a pretty much in place replacement for the older DocumentQuery.
Original DocumentClient method for comparison:
IDocumentQuery<ToDoItem> query = client.CreateDocumentQuery<ToDoItem>(collectionUri)
.Where(t => t.Description.Contains(searchterm))
.AsDocumentQuery();
while (query.HasMoreResults)
{
foreach (ToDoItem result in await query.ExecuteNextAsync())
{
log.LogInformation(result.Description);
}
}
Using a CosmosClient this becomes:
var database = client.GetDatabase("ToDoItems");
var container = database.GetContainer("Items");
var query = container.GetItemLinqQueryable<ToDoItem>()
.Where(t => t.Description.Contains(searchTerm))
.ToFeedIterator();
while (query.HasMoreResults)
{
foreach (ToDoItem result in await query.ReadNextAsync())
{
log.LogInformation(result.Description);
}
}
So your query is now a FeedIterator, and you can call HasMoreResults and ReadNextAsync on it.
Admittedly this won't get you access to the diagnostics, request charge, etc. that comes on the FeedIterator, but it will page through the results cleanly.
IQueryable<returnVModel> query;
var requestOptions = new QueryRequestOptions
{
MaxItemCount = 20
};
if (Token == "" || Token == null)
{
query = Container.GetItemLinqQueryable<returnVModel>(false, null, requestOptions).Where(x => x.id == id);
}
else
{
query = Container.GetItemLinqQueryable<returnVModel>(false, Token, requestOptions).Where(x => x.id == id);
}
var ct = new CancellationTokenSource();
var totalCount = await query.CountAsync(ct.Token); //Total Count
var feedIterator = query.ToFeedIterator();
var queryResults = new List<returnVModel>();
FeedResponse<returnVModel> feedResults = await feedIterator.ReadNextAsync(ct.Token);
queryResults.AddRange(feedResults); // Output
var PaginationToken = feedResults.ContinuationToken //Token
First time we need to pass token as null, from next page onwards pass the token which we received in previous output.
Pagination was working fine in v3.

TLSharp Send message to a group

//get user dialogs
var dialogs = await client.GetUserDialogsAsync() as TLDialogs;
//find channel by title
var chat = dialogs.Chats
.Where(c => c.GetType() == typeof(TLChat))
.Cast<TLChat>()
.FirstOrDefault(c => c.Title == "zgzxbhsrbhdrbh");
//send message
await client.SendMessageAsync(new TLInputPeerChannel() { ChannelId = chat.Id },
"OUR_MESSAGE");
I`m trying this code, but it returns me InvalidOperationException: CHANNEL_INVALID. Can someone help?
You were quite right.
//Get dialogs
var dialogs = await client.GetUserDialogsAsync();
//get user chats
var chats = ((TeleSharp.TL.Messages.TLDialogsSlice)dialogs).Chats;
//find channel by title
var tlChannel = chats.Where(_ => _.GetType() == typeof(TLChannel))
.Select(_=>(TLChannel)_)
.Where(_=>_.Title.Contains("<Channel-Name>"))
.FirstOrDefault();
//send message
await client.SendMessageAsync(new TLInputPeerChannel()
{ ChannelId = tlChannel.Id, AccessHash =(long)tlChannel.AccessHash },
"OUR_MESSAGE");
There is a difference between sending to a group and sending to a channel
In your code, at the end of it, you called a command to send to a channel, and in the first one, you specified the type as a group. This is the latest exception. You can try this code and, God willing, the problem will be solved.
//get user dialogs
var dialogs = (TLDialogsSlice)await client.GetUserDialogsAsync();
//find channel by title
var chat = dialogs.Chats
.Where(c => c.GetType() == typeof(TLChat))
.Cast<TLChat>()
.FirstOrDefault(c => c.Title == "zgzxbhsrbhdrbh");
//send message
await client.SendMessageAsync(new TLInputPeerChat() { ChatId = chat.Id }, "OUR_MESSAGE");

Test connection with TLSharp

I'm trying to send a message with TLSharp but cant,i dont get errors,it just execute the code and do nothing;
This is my method.
public virtual async Task SendMessageTest()
{
string NumberToSendMessage = "+55199999999";
if (string.IsNullOrWhiteSpace(NumberToSendMessage))
throw new Exception("TESTE");
// this is because the contacts in the address come without the "+" prefix
var normalizedNumber = NumberToSendMessage.StartsWith("+") ?
NumberToSendMessage.Substring(1, NumberToSendMessage.Length - 1) :
NumberToSendMessage;
var client = NewClient();
var tsk = client.ConnectAsync();
await client.ConnectAsync();
var result = await client.GetContactsAsync();
var user = result.users.lists
.OfType<TLUser>()
.FirstOrDefault(x => x.phone == normalizedNumber);
if (user == null)
{
throw new System.Exception("Number was not found in Contacts List of user: " + NumberToSendMessage);
}
await client.SendTypingAsync(new TLInputPeerUser() { user_id = user.id });
Thread.Sleep(3000);
await client.SendMessageAsync(new TLInputPeerUser() { user_id = user.id }, "TEST");
}
This is my code,is says is wait for activation,what should i do?
I'm trying to use this method also,but it doenst return nothing too.
I'm new to TelegramApi,what i'm doing wrong?
await client.ConnectAsync();
You should authorize first! And only after that you can call other methods. Look at the examples here.
In general you should write something like this:
var hash = await client.SendCodeRequestAsync(NotRegisteredNumberToSignUp);
var code = Console.ReadLine(); //Input the code, that was sent to your phone
var loggedInUser = await client.MakeAuthAsync(NotRegisteredNumberToSignUp, hash, code);

Refit / HttpClient / ModernHttpClient - 400 Bad Request

Recently started with ReactiveUI and so far so good. While trying to figure out stuff I came across a HttpClient / Refit problem. I have a long list and every item in that list have to make a request to a API as follows.
This is a ReactiveObject
public SearchResult()
{
LoadStats = ReactiveCommand.CreateAsyncTask(_ => DownloadMultipleCalls(this.IdText, this.DisplayText));
LoadStats
.ThrownExceptions
.SubscribeOn(RxApp.MainThreadScheduler)
.Subscribe(ex => UserError.Throw("Couldn't load stats", ex));
_avaText = LoadStats.Select(x => x.Ava).ToProperty(this, x => x.AvaText, string.Empty);
_perText = LoadStats.Select(x => x.Per).ToProperty(this, x => x.PerText, string.Empty);
this.WhenAnyValue(x => x.IdText)
.Where(x => !string.IsNullOrWhiteSpace(x))
//.Select(_ => Observable.Timer(DateTimeOffset.MinValue, TimeSpan.FromSeconds(1), RxApp.MainThreadScheduler))
.Retry(5)
.InvokeCommand(LoadStats);
}
In DownloadMultipleCalls the following is happening.
async static Task<AvaPer> DownloadMultipleCalls(string id, string displaytext)
{
AvaPer response = new AvaPer();
var block = new ActionBlock<string>(async service =>
{
response = await DownloadCall(service, displaytext);
},
new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 4 });
block.Post(id);
block.Complete();
await block.Completion;
return response;
}
async static Task<AvaPer> DownloadCall(string id, string displaytext)
{
System.Diagnostics.Debug.WriteLine($"Starting download at {DateTimeOffset.Now}");
var client = new HttpClient(NetCache.UserInitiated)
{
BaseAddress = new Uri("https://api.adres.com"),
};
//client.Timeout = TimeSpan.FromMilliseconds(10);
var token = GetToken;
client.DefaultRequestHeaders.Add("authToken", token);
var api = RestService.For<IMyApi>(client);
AvaPer idEntries = new AvaPer();
try
{
var searchResult = await api.GetAvaPerStatusRaw(id); // <== Here is the error (400 - Bad Request)
//var parsedEntries = Task.Run(() => {
idEntries = new AvaPer
{
Id = searchResult.Id.ToString() ?? string.Empty,
display = displaytext ?? string.Empty,
Ava = searchResult.AvailabilityStatus ?? string.Empty,
Per = searchResult.PerformanceStatus ?? string.Empty,
Updated = DateTimeOffset.Now.ToLocalTime().ToString() ?? string.Empty
};
//}).ConfigureAwait(false);
//return idEntries;
}
catch (ApiException ex)
{
var statusCode = ex.StatusCode;
var error = ex.GetContentAs<Models.ServiceModel.ErrorResponse>();
}
return idEntries;
}
Finally it goes all wrong with this line of code var searchResult = await api.GetAvaPerStatusRaw(id); The app crashes with a response "400 Bad Request" and if I look into the error it sais that the there is no id value inplace of the GET request. But when I check the initial value of id there is a value so it should not respond with that. Can anyone help me with this? If you have any question, please do not hesitate to ask. Thank you very much.
Kind regards,
Fernando

Outlook Contacts API - Paging Results

I'm trying to display ALL the Outlook contacts for a selected account. When an account has a few thousand contacts, the following code only shows the first n contacts. The contactResults object has a MorePagesAvailable property and a GetNextPageAsync() method available, but I clearly do NOT know how to use them. Can someone please enlighten me.
string token = (string)Session["access_token"];
string email = (string)Session["user_email"];
// Since we have the token locally from the Session, just return it here
OutlookServicesClient client = new OutlookServicesClient(new Uri("https://outlook.office.com/api/v2.0"), async () => { return token; });
client.Context.SendingRequest2 += new EventHandler<SendingRequest2EventArgs>((sender, e) => InsertXAnchorMailboxHeader(sender, e, email));
var contactResults = await client.Me.Contacts
.OrderBy(c => c.DisplayName)
.Take(2500)
.Select(c => new DisplayContact(c))
.ExecuteAsync();
foreach (DisplayContact displayContact in contactResults.CurrentPage)
System.Diagnostics.Debug.WriteLine(displayContact);
var contactResults = await client.Me.Contacts
.OrderBy(c => c.DisplayName)
.Select(c => new DisplayContact(c))
.ExecuteAsync();
while (true)
{
foreach (DisplayContact displayContact in contactResults.CurrentPage)
System.Diagnostics.Debug.WriteLine(displayContact);
if (contactResults.MorePagesAvailable)
contactResults = await contactResults.GetNextPageAsync();
else
break;
}

Categories

Resources