LinqToTwitter 列出自指定日期以来的 DM
LinqToTwitter List DMs since a specified date
是否可以在指定日期后列出私信?如果我有大量直接消息,并且必须翻阅许多结果,我将很快达到速率限制。我想跟踪上次查询 DirectMessageEventsType.List
的时间,并将下一次查询限制为仅在该日期后的 sent/received 消息。
您可能已经知道,Twitter API 中用于列出 DM 的唯一参数是 count
和 cursor
。也就是说,这里有一个可能很方便的解决方法。它涉及到 LINQ to Objects 查询之后的 LINQ to Twitter 查询:
using System;
using System.Linq;
using System.Collections.Generic;
using System.Threading.Tasks;
using LinqToTwitter;
using LinqToTwitter.OAuth;
using System.Diagnostics;
namespace TwitterDMListDate
{
class Program
{
static async Task Main()
{
TwitterContext twitterCtx = await GetTwitterContext();
int count = 50; // set to a low number to demo paging
string cursor = "";
List<DMEvent> allDmEvents = new();
bool isPastCreatedAt = false;
DateTime lastCreatedAt = DateTime.UtcNow.AddHours(-1);
// you don't have a valid cursor until after the first query
DirectMessageEvents dmResponse =
await
(from dm in twitterCtx.DirectMessageEvents
where dm.Type == DirectMessageEventsType.List &&
dm.Count == count
select dm)
.SingleOrDefaultAsync();
isPastCreatedAt = CheckPastCreatedAt(dmResponse, lastCreatedAt);
allDmEvents.AddRange(dmResponse?.Value?.DMEvents ?? new List<DMEvent>());
cursor = dmResponse?.Value?.NextCursor ?? "";
while (!string.IsNullOrWhiteSpace(cursor) && !isPastCreatedAt)
{
dmResponse =
await
(from dm in twitterCtx.DirectMessageEvents
where dm.Type == DirectMessageEventsType.List &&
dm.Count == count &&
dm.Cursor == cursor
select dm)
.SingleOrDefaultAsync();
allDmEvents.AddRange(dmResponse?.Value?.DMEvents ?? new List<DMEvent>());
cursor = dmResponse?.Value?.NextCursor ?? "";
isPastCreatedAt = CheckPastCreatedAt(dmResponse, lastCreatedAt);
}
if (!allDmEvents.Any())
{
Console.WriteLine("No items returned");
return;
}
Console.WriteLine($"Response Count: {allDmEvents.Count}");
Console.WriteLine("Responses:");
allDmEvents.ForEach(evt =>
{
DirectMessageCreate? msgCreate = evt.MessageCreate;
if (evt != null && msgCreate != null)
Console.WriteLine(
$"DM ID: {evt.ID}\n" +
$"From ID: {msgCreate.SenderID ?? "None"}\n" +
$"To ID: {msgCreate.Target?.RecipientID ?? "None"}\n" +
$"Message Text: {msgCreate.MessageData?.Text ?? "None"}\n");
});
}
static bool CheckPastCreatedAt(DirectMessageEvents dmResponse, DateTime lastCreatedAt)
{
return
(from dm in dmResponse.Value.DMEvents
where dm.CreatedAt <= lastCreatedAt
select dm)
.Any();
}
static async Task<TwitterContext> GetTwitterContext()
{
var auth = new PinAuthorizer()
{
CredentialStore = new InMemoryCredentialStore
{
ConsumerKey = "",
ConsumerSecret = ""
},
GoToTwitterAuthorization = pageLink =>
{
var psi = new ProcessStartInfo
{
FileName = pageLink,
UseShellExecute = true
};
Process.Start(psi);
},
GetPin = () =>
{
Console.WriteLine(
"\nAfter authorizing this application, Twitter " +
"will give you a 7-digit PIN Number.\n");
Console.Write("Enter the PIN number here: ");
return Console.ReadLine() ?? string.Empty;
}
};
await auth.AuthorizeAsync();
var twitterCtx = new TwitterContext(auth);
return twitterCtx;
}
}
}
实现此功能的两个变量是 isPastCreatedAt
和 lastCreatedAt
。 isPastCreatedAt
标记一组 DM(来自大小为 count
的查询)包含一个或多个早于特定日期的 DM 的情况。符合 isPastCreatedAt
条件的日期是 lastCreatedAt
。本质上,一旦我们有早于 lastCreatedAt
的推文,我们不想继续查询,因为后续查询保证 return 所有早于 lastCreatedAt
.
的推文
该演示将 lastCreatedAt
设置为提前一个小时。请注意,它使用的是 UTC 时间,因为那是 Twitter 使用的时间。在您的应用程序中,您应该跟踪这个时间,将其重新设置为自上次查询以来收到的最旧推文的 CreatedAt
属性。
每次 LINQ to Twitter 查询 DM 后,都会调用 CheckPastCreatedAt
。这是设置 isPastCreatedAt
的地方。该方法内部是一个 LINQ to Objects 查询。它查询 LINQ to Twitter 刚刚 returned 的 DM 列表,检查是否有任何 DM 包含早于 lastCreatedAt
日期的日期。它使用 CreatedAt
属性,顾名思义,这是此演示中变量和方法命名的原因,以确保查询不会过度浪费速率限制。它还使用了 Any
运算符,这比 Count
效率高得多,但我跑题了。
请注意,Main
中的 while
语句向您可能用来遍历游标的内容添加了一个附加条件:&& !isPastCreatedAt
。这就是防止您走得太远和浪费速率限制的原因。
完成后您只需要再做一件事 - 过滤掉您已经收到的 DM 以避免重复。然而,我的直觉是你已经知道了。
虽然这不是您可能希望得到的答案,但它确实为使用 Twitter API 的任何人概述了一个重要模式,无论是 LINQ to Twitter 还是其他任何一个优秀的库.也就是说,使用 Twitter API 提供的内容进行查询,然后在本地过滤结果。虽然其他一些库提供了额外的抽象,有时感觉它们很有帮助,但 LINQ to Twitter 采用了一种更原始的方法来更接近 Twitter API 本身。在这种情况下,最好直观地了解什么是越线的,这样您就可以推断出满足您需求的其他解决方案。
是否可以在指定日期后列出私信?如果我有大量直接消息,并且必须翻阅许多结果,我将很快达到速率限制。我想跟踪上次查询 DirectMessageEventsType.List
的时间,并将下一次查询限制为仅在该日期后的 sent/received 消息。
您可能已经知道,Twitter API 中用于列出 DM 的唯一参数是 count
和 cursor
。也就是说,这里有一个可能很方便的解决方法。它涉及到 LINQ to Objects 查询之后的 LINQ to Twitter 查询:
using System;
using System.Linq;
using System.Collections.Generic;
using System.Threading.Tasks;
using LinqToTwitter;
using LinqToTwitter.OAuth;
using System.Diagnostics;
namespace TwitterDMListDate
{
class Program
{
static async Task Main()
{
TwitterContext twitterCtx = await GetTwitterContext();
int count = 50; // set to a low number to demo paging
string cursor = "";
List<DMEvent> allDmEvents = new();
bool isPastCreatedAt = false;
DateTime lastCreatedAt = DateTime.UtcNow.AddHours(-1);
// you don't have a valid cursor until after the first query
DirectMessageEvents dmResponse =
await
(from dm in twitterCtx.DirectMessageEvents
where dm.Type == DirectMessageEventsType.List &&
dm.Count == count
select dm)
.SingleOrDefaultAsync();
isPastCreatedAt = CheckPastCreatedAt(dmResponse, lastCreatedAt);
allDmEvents.AddRange(dmResponse?.Value?.DMEvents ?? new List<DMEvent>());
cursor = dmResponse?.Value?.NextCursor ?? "";
while (!string.IsNullOrWhiteSpace(cursor) && !isPastCreatedAt)
{
dmResponse =
await
(from dm in twitterCtx.DirectMessageEvents
where dm.Type == DirectMessageEventsType.List &&
dm.Count == count &&
dm.Cursor == cursor
select dm)
.SingleOrDefaultAsync();
allDmEvents.AddRange(dmResponse?.Value?.DMEvents ?? new List<DMEvent>());
cursor = dmResponse?.Value?.NextCursor ?? "";
isPastCreatedAt = CheckPastCreatedAt(dmResponse, lastCreatedAt);
}
if (!allDmEvents.Any())
{
Console.WriteLine("No items returned");
return;
}
Console.WriteLine($"Response Count: {allDmEvents.Count}");
Console.WriteLine("Responses:");
allDmEvents.ForEach(evt =>
{
DirectMessageCreate? msgCreate = evt.MessageCreate;
if (evt != null && msgCreate != null)
Console.WriteLine(
$"DM ID: {evt.ID}\n" +
$"From ID: {msgCreate.SenderID ?? "None"}\n" +
$"To ID: {msgCreate.Target?.RecipientID ?? "None"}\n" +
$"Message Text: {msgCreate.MessageData?.Text ?? "None"}\n");
});
}
static bool CheckPastCreatedAt(DirectMessageEvents dmResponse, DateTime lastCreatedAt)
{
return
(from dm in dmResponse.Value.DMEvents
where dm.CreatedAt <= lastCreatedAt
select dm)
.Any();
}
static async Task<TwitterContext> GetTwitterContext()
{
var auth = new PinAuthorizer()
{
CredentialStore = new InMemoryCredentialStore
{
ConsumerKey = "",
ConsumerSecret = ""
},
GoToTwitterAuthorization = pageLink =>
{
var psi = new ProcessStartInfo
{
FileName = pageLink,
UseShellExecute = true
};
Process.Start(psi);
},
GetPin = () =>
{
Console.WriteLine(
"\nAfter authorizing this application, Twitter " +
"will give you a 7-digit PIN Number.\n");
Console.Write("Enter the PIN number here: ");
return Console.ReadLine() ?? string.Empty;
}
};
await auth.AuthorizeAsync();
var twitterCtx = new TwitterContext(auth);
return twitterCtx;
}
}
}
实现此功能的两个变量是 isPastCreatedAt
和 lastCreatedAt
。 isPastCreatedAt
标记一组 DM(来自大小为 count
的查询)包含一个或多个早于特定日期的 DM 的情况。符合 isPastCreatedAt
条件的日期是 lastCreatedAt
。本质上,一旦我们有早于 lastCreatedAt
的推文,我们不想继续查询,因为后续查询保证 return 所有早于 lastCreatedAt
.
该演示将 lastCreatedAt
设置为提前一个小时。请注意,它使用的是 UTC 时间,因为那是 Twitter 使用的时间。在您的应用程序中,您应该跟踪这个时间,将其重新设置为自上次查询以来收到的最旧推文的 CreatedAt
属性。
每次 LINQ to Twitter 查询 DM 后,都会调用 CheckPastCreatedAt
。这是设置 isPastCreatedAt
的地方。该方法内部是一个 LINQ to Objects 查询。它查询 LINQ to Twitter 刚刚 returned 的 DM 列表,检查是否有任何 DM 包含早于 lastCreatedAt
日期的日期。它使用 CreatedAt
属性,顾名思义,这是此演示中变量和方法命名的原因,以确保查询不会过度浪费速率限制。它还使用了 Any
运算符,这比 Count
效率高得多,但我跑题了。
请注意,Main
中的 while
语句向您可能用来遍历游标的内容添加了一个附加条件:&& !isPastCreatedAt
。这就是防止您走得太远和浪费速率限制的原因。
完成后您只需要再做一件事 - 过滤掉您已经收到的 DM 以避免重复。然而,我的直觉是你已经知道了。
虽然这不是您可能希望得到的答案,但它确实为使用 Twitter API 的任何人概述了一个重要模式,无论是 LINQ to Twitter 还是其他任何一个优秀的库.也就是说,使用 Twitter API 提供的内容进行查询,然后在本地过滤结果。虽然其他一些库提供了额外的抽象,有时感觉它们很有帮助,但 LINQ to Twitter 采用了一种更原始的方法来更接近 Twitter API 本身。在这种情况下,最好直观地了解什么是越线的,这样您就可以推断出满足您需求的其他解决方案。