Inumedia / SlackAPI

.NET Implementation of the Slack team communication platform API.
MIT License
451 stars 243 forks source link

SlackTaskClient.DeleteMessageAsync takes a datetime but should take a timestamp string #299

Open mdiluz opened 2 years ago

mdiluz commented 2 years ago

DeleteMessageAsync for the task client seems to be written to match the one in the socket client, which understands timestamps as date times, but the API requires the timestamp as a string including microseconds.

Demonstrated in code below:

var response = await SlackTaskClient.PostMessageAsync(recipient, item.Message);
if (!response.ok)
    throw new Exception(response.error);

// response.ts e.g. 1645450156.370359
var baseTimestamp = response.ts.Replace(".",""); // Remove the bullet point
var ts = long.Parse(baseTimestamp) / 1000; // Problem: We have to lose the milliseconds here
var time = DateTimeOffset.FromUnixTimeMilliseconds(ts).DateTime; // Convert to a DateTime

var deletedResponse = await SlackTaskClient.DeleteMessageAsync(response.channel, time); 
if (!deletedResponse.ok)
    throw new Exception(deletedResponse.error); // We fail with message_not_found

Slack needs the full ts string with the unique digits after the ., not a real timestamp, so DeleteMessageAsync can't work here as I don't think you can stick the microseconds back into a DateTime (and I don't think ToProperTimeStamp can convert and add the .).

The workaround for now is simply to make the call manually:

var deletedResponse = await SlackTaskClient.APIRequestWithTokenAsync<DeletedResponse>(new List<Tuple<string, string>>()
{
    new("ts", response.ts),
    new("channel", response.channel)
}.ToArray());

if (!deletedResponse.ok)
    throw new Exception(deletedResponse.error);
ceciliachan1979 commented 1 year ago

@mdiluz This will preserve the milliseconds.

            decimal doubleTimestamp = Decimal.Parse(response.ts);
            long longTimestamp = (long)(doubleTimestamp * 10000000m);
            DateTime unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
            return unixEpoch.AddTicks(longTimestamp);

There are other APIs (such as GetConversationsHistoryAsync) that return timestamps as DateTime, maybe we can consider changing PostMessageAsync to return DateTime instead?