feat: status

oneRain 2021-01-13 17:55:17 +08:00
parent cf87916b8c
commit aec1551cb7
6 changed files with 308 additions and 5 deletions

View File

@ -85,6 +85,50 @@ namespace Storage.Test {
Assert.AreEqual(followersAndFollowees.FolloweesCount, 1);
}
[Test]
[Order(3)]
public async Task Send() {
await LCUser.BecomeWithSessionToken(user1.SessionToken);
// 给粉丝发送状态
LCStatus status = new LCStatus {
Data = new Dictionary<string, object> {
{ "image", "xxx.jpg" },
{ "content", "hello, world" }
}
};
await LCStatus.SendToFollowers(status);
// 给某个用户发送私信
LCStatus privateStatus = new LCStatus {
Data = new Dictionary<string, object> {
{ "image", "xxx.jpg" },
{ "content", "hello, game" }
}
};
await LCStatus.SendPrivately(status, user2.ObjectId);
}
[Test]
[Order(4)]
public async Task Query() {
await LCUser.BecomeWithSessionToken(user2.SessionToken);
LCStatusCount statusCount = await LCStatus.GetCount(LCStatus.InboxTypeDefault);
Assert.Greater(statusCount.Total, 0);
LCStatusCount privateCount = await LCStatus.GetCount(LCStatus.InboxTypePrivate);
Assert.Greater(privateCount.Total, 0);
LCStatusQuery query = new LCStatusQuery(LCStatus.InboxTypeDefault);
ReadOnlyCollection<LCStatus> statuses = await query.Find();
foreach (LCStatus status in statuses) {
Assert.AreEqual((status["source"] as LCObject).ObjectId, user1.ObjectId);
await status.Delete();
}
await LCStatus.ResetUnreadCount(LCStatus.InboxTypePrivate);
}
[Test]
[Order(5)]
public async Task Unfollow() {

View File

@ -136,15 +136,25 @@ namespace LeanCloud.Storage.Internal.Http {
throw HandleErrorResponse(response.StatusCode, resultString);
}
public async Task Delete(string path) {
string url = await BuildUrl(path);
public async Task Delete(string path,
Dictionary<string, object> headers = null,
object data = null,
Dictionary<string, object> queryParams = null) {
string url = await BuildUrl(path, queryParams);
HttpRequestMessage request = new HttpRequestMessage {
RequestUri = new Uri(url),
Method = HttpMethod.Delete
};
await FillHeaders(request.Headers);
await FillHeaders(request.Headers, headers);
LCHttpUtils.PrintRequest(client, request);
string content = null;
if (data != null) {
content = JsonConvert.SerializeObject(data);
StringContent requestContent = new StringContent(content);
requestContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
request.Content = requestContent;
}
LCHttpUtils.PrintRequest(client, request, content);
HttpResponseMessage response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
request.Dispose();
@ -153,7 +163,7 @@ namespace LeanCloud.Storage.Internal.Http {
LCHttpUtils.PrintResponse(response, resultString);
if (response.IsSuccessStatusCode) {
Dictionary<string, object> ret = JsonConvert.DeserializeObject<Dictionary<string, object>>(resultString,
_ = JsonConvert.DeserializeObject<Dictionary<string, object>>(resultString,
LCJsonConverter.Default);
return;
}

View File

@ -61,6 +61,7 @@ namespace LeanCloud {
LCObject.RegisterSubclass(LCUser.CLASS_NAME, () => new LCUser());
LCObject.RegisterSubclass(LCRole.CLASS_NAME, () => new LCRole());
LCObject.RegisterSubclass(LCFile.CLASS_NAME, () => new LCFile());
LCObject.RegisterSubclass(LCStatus.CLASS_NAME, () => new LCStatus());
LCObject.RegisterSubclass(LCFriendshipRequest.CLASS_NAME, () => new LCFriendshipRequest());
AppRouter = new LCAppRouter(appId, server);

176
Storage/Storage/LCStatus.cs Normal file
View File

@ -0,0 +1,176 @@
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using LeanCloud.Storage.Internal.Codec;
using LeanCloud.Storage.Internal.Object;
using Newtonsoft.Json;
namespace LeanCloud.Storage {
public class LCStatus : LCObject {
public const string CLASS_NAME = "_Status";
/// Public, shown on followees' timeline.
public const string InboxTypeDefault = "default";
/// Private.
public const string InboxTypePrivate = "private";
/// Keys
public const string SourceKey = "source";
public const string InboxTypeKey = "inboxType";
public const string OwnerKey = "owner";
public const string MessageIdKey = "messageId";
public int MessageId {
get; internal set;
}
public string InboxType {
get; internal set;
}
private LCQuery query;
public Dictionary<string, object> Data {
get; set;
}
public LCStatus() : base(CLASS_NAME) {
InboxType = InboxTypeDefault;
Data = new Dictionary<string, object>();
}
public static async Task<LCStatus> SendToFollowers(LCStatus status) {
if (status == null) {
throw new ArgumentNullException(nameof(status));
}
LCUser user = await LCUser.GetCurrent();
if (user == null) {
throw new ArgumentNullException("current user");
}
status.Data[SourceKey] = user;
LCQuery<LCObject> query = new LCQuery<LCObject>("_Follower")
.WhereEqualTo("user", user)
.Select("follower");
status.query = query;
status.InboxType = InboxTypeDefault;
return await status.Send();
}
public static async Task<LCStatus> SendPrivately(LCStatus status, string targetId) {
if (status == null) {
throw new ArgumentNullException(nameof(status));
}
if (string.IsNullOrEmpty(targetId)) {
throw new ArgumentNullException(nameof(targetId));
}
LCUser user = await LCUser.GetCurrent();
if (user == null) {
throw new ArgumentNullException("current user");
}
status.Data[SourceKey] = user;
LCQuery<LCObject> query = new LCQuery<LCObject>("_User")
.WhereEqualTo("objectId", targetId);
status.query = query;
status.InboxType = InboxTypePrivate;
return await status.Send();
}
public async Task<LCStatus> Send() {
LCUser user = await LCUser.GetCurrent();
if (user == null) {
throw new ArgumentNullException("current user");
}
Dictionary<string, object> formData = new Dictionary<string, object> {
{ InboxTypeKey, InboxType }
};
if (Data != null) {
formData["data"] = LCEncoder.Encode(Data);
}
if (query != null) {
Dictionary<string, object> queryData = new Dictionary<string, object> {
{ "className", query.ClassName }
};
Dictionary<string, object> ps = query.BuildParams();
if (ps.TryGetValue("where", out object whereObj) &&
whereObj is string where) {
queryData["where"] = JsonConvert.DeserializeObject(where);
}
if (ps.TryGetValue("keys", out object keys)) {
queryData["keys"] = keys;
}
formData["query"] = queryData;
}
Dictionary<string, object> response = await LCApplication.HttpClient.Post<Dictionary<string, object>>("statuses",
data: formData);
LCObjectData objectData = LCObjectData.Decode(response);
Merge(objectData);
return this;
}
public new async Task Delete() {
LCUser user = await LCUser.GetCurrent();
if (user == null) {
throw new ArgumentNullException("current user");
}
LCUser source = (Data[SourceKey] ?? this[SourceKey]) as LCUser;
if (source != null && source.ObjectId == user.ObjectId) {
await LCApplication.HttpClient.Delete($"statuses/{ObjectId}");
} else {
Dictionary<string, object> data = new Dictionary<string, object> {
{ OwnerKey, JsonConvert.SerializeObject(LCEncoder.Encode(user)) },
{ InboxTypeKey, InboxType },
{ MessageIdKey, MessageId }
};
await LCApplication.HttpClient.Delete("subscribe/statuses/inbox", queryParams: data);
}
}
public static async Task<LCStatusCount> GetCount(string inboxType) {
LCUser user = await LCUser.GetCurrent();
if (user == null) {
throw new ArgumentNullException("current user");
}
Dictionary<string, object> queryParams = new Dictionary<string, object> {
{ OwnerKey, JsonConvert.SerializeObject(LCEncoder.Encode(user)) }
};
if (!string.IsNullOrEmpty(inboxType)) {
queryParams[InboxTypeKey] = inboxType;
}
Dictionary<string, object> response = await LCApplication.HttpClient.Get<Dictionary<string, object>>("subscribe/statuses/count",
queryParams: queryParams);
LCStatusCount statusCount = new LCStatusCount {
Total = (int)response["total"],
Unread = (int)response["unread"]
};
return statusCount;
}
public static async Task ResetUnreadCount(string inboxType = null) {
LCUser user = await LCUser.GetCurrent();
if (user == null) {
throw new ArgumentNullException("current user");
}
Dictionary<string, object> queryParams = new Dictionary<string, object> {
{ OwnerKey, JsonConvert.SerializeObject(LCEncoder.Encode(user)) }
};
if (!string.IsNullOrEmpty(inboxType)) {
queryParams[InboxTypeKey] = inboxType;
}
await LCApplication.HttpClient.Post<Dictionary<string, object>>("subscribe/statuses/resetUnreadCount",
queryParams:queryParams);
}
}
}

View File

@ -0,0 +1,11 @@
namespace LeanCloud.Storage {
public class LCStatusCount {
public int Total {
get; set;
}
public int Unread {
get; set;
}
}
}

View File

@ -0,0 +1,61 @@
using System;
using System.Threading.Tasks;
using System.Collections;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using Newtonsoft.Json;
using LeanCloud.Storage.Internal.Codec;
using LeanCloud.Storage.Internal.Object;
namespace LeanCloud.Storage {
public class LCStatusQuery : LCQuery<LCStatus> {
public string InboxType {
get; set;
}
public int SinceId {
get; set;
}
public int MaxId {
get; set;
}
public LCStatusQuery(string inboxType = LCStatus.InboxTypeDefault) : base("_Status") {
InboxType = inboxType;
SinceId = 0;
MaxId = 0;
}
public async Task<ReadOnlyCollection<LCStatus>> Find() {
LCUser user = await LCUser.GetCurrent();
if (user == null) {
throw new ArgumentNullException("current user");
}
Dictionary<string, object> queryParams = new Dictionary<string, object> {
{ LCStatus.OwnerKey, JsonConvert.SerializeObject(LCEncoder.Encode(user)) },
{ LCStatus.InboxTypeKey, InboxType },
{ "where", BuildWhere() },
{ "sinceId", SinceId },
{ "maxId", MaxId },
{ "limit", Condition.Limit }
};
Dictionary<string, object> response = await LCApplication.HttpClient.Get<Dictionary<string, object>>("subscribe/statuses",
queryParams: queryParams);
List<object> results = response["results"] as List<object>;
List<LCStatus> statuses = new List<LCStatus>();
foreach (object item in results) {
LCObjectData objectData = LCObjectData.Decode(item as IDictionary);
LCStatus status = new LCStatus();
status.Merge(objectData);
status.MessageId = (int)objectData.CustomPropertyDict[LCStatus.MessageIdKey];
status.Data = objectData.CustomPropertyDict;
status.InboxType = objectData.CustomPropertyDict[LCStatus.InboxTypeKey] as string;
statuses.Add(status);
}
return statuses.AsReadOnly();
}
}
}