feat: status
parent
cf87916b8c
commit
aec1551cb7
|
@ -85,6 +85,50 @@ namespace Storage.Test {
|
||||||
Assert.AreEqual(followersAndFollowees.FolloweesCount, 1);
|
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]
|
[Test]
|
||||||
[Order(5)]
|
[Order(5)]
|
||||||
public async Task Unfollow() {
|
public async Task Unfollow() {
|
||||||
|
|
|
@ -136,15 +136,25 @@ namespace LeanCloud.Storage.Internal.Http {
|
||||||
throw HandleErrorResponse(response.StatusCode, resultString);
|
throw HandleErrorResponse(response.StatusCode, resultString);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Delete(string path) {
|
public async Task Delete(string path,
|
||||||
string url = await BuildUrl(path);
|
Dictionary<string, object> headers = null,
|
||||||
|
object data = null,
|
||||||
|
Dictionary<string, object> queryParams = null) {
|
||||||
|
string url = await BuildUrl(path, queryParams);
|
||||||
HttpRequestMessage request = new HttpRequestMessage {
|
HttpRequestMessage request = new HttpRequestMessage {
|
||||||
RequestUri = new Uri(url),
|
RequestUri = new Uri(url),
|
||||||
Method = HttpMethod.Delete
|
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);
|
HttpResponseMessage response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
|
||||||
request.Dispose();
|
request.Dispose();
|
||||||
|
|
||||||
|
@ -153,7 +163,7 @@ namespace LeanCloud.Storage.Internal.Http {
|
||||||
LCHttpUtils.PrintResponse(response, resultString);
|
LCHttpUtils.PrintResponse(response, resultString);
|
||||||
|
|
||||||
if (response.IsSuccessStatusCode) {
|
if (response.IsSuccessStatusCode) {
|
||||||
Dictionary<string, object> ret = JsonConvert.DeserializeObject<Dictionary<string, object>>(resultString,
|
_ = JsonConvert.DeserializeObject<Dictionary<string, object>>(resultString,
|
||||||
LCJsonConverter.Default);
|
LCJsonConverter.Default);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,6 +61,7 @@ namespace LeanCloud {
|
||||||
LCObject.RegisterSubclass(LCUser.CLASS_NAME, () => new LCUser());
|
LCObject.RegisterSubclass(LCUser.CLASS_NAME, () => new LCUser());
|
||||||
LCObject.RegisterSubclass(LCRole.CLASS_NAME, () => new LCRole());
|
LCObject.RegisterSubclass(LCRole.CLASS_NAME, () => new LCRole());
|
||||||
LCObject.RegisterSubclass(LCFile.CLASS_NAME, () => new LCFile());
|
LCObject.RegisterSubclass(LCFile.CLASS_NAME, () => new LCFile());
|
||||||
|
LCObject.RegisterSubclass(LCStatus.CLASS_NAME, () => new LCStatus());
|
||||||
LCObject.RegisterSubclass(LCFriendshipRequest.CLASS_NAME, () => new LCFriendshipRequest());
|
LCObject.RegisterSubclass(LCFriendshipRequest.CLASS_NAME, () => new LCFriendshipRequest());
|
||||||
|
|
||||||
AppRouter = new LCAppRouter(appId, server);
|
AppRouter = new LCAppRouter(appId, server);
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
namespace LeanCloud.Storage {
|
||||||
|
public class LCStatusCount {
|
||||||
|
public int Total {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Unread {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue