Code Monkey home page Code Monkey logo

stream-chat-net's Introduction

Official .NET SDK for Stream Chat

.github/workflows/ci.yaml NuGet Badge

Official .NET API client for Stream Chat, a service for building chat applications.
Explore the docs »

Code Samples · Report Bug · Request Feature

📝 About Stream

You can sign up for a Stream account at our Get Started page.

You can use this library to access chat API endpoints server-side.

For the client-side integrations (web and mobile) have a look at the JavaScript, iOS and Android SDK libraries (docs).


🚨 Breaking changes in v1.0 <

The library received many changes in v1.0 to make it easier to use and more maintanable in the future. The main change is that both Channel and Client classes have been separated into small modules that we call clients. (This resambles the structure of our Java library as well.) Main changes:

  • Channel and Client classes are gone, and have been organized into smaller clients in StreamChat.Clients namespace.
  • These clients do not maintain state as Channel used to did earlier where it kept the channelType and channelId in the memory. So this means that you'll need to pass in channelType and channelId to a lot of method calls in IChannelClient.
  • Async method names have Async suffix now.
  • All public methods and classes have documentation.
  • Identifiers has been renamed from ID to Id to follow Microsoft's naming guide. Such as userID -> userId.
  • A lot of data classes have been renamed to make more sense. Such as ChannelObject -> Channel.
  • Data classes have been moved to StreamChat.Models namespace.
  • Full feature parity: all backend APIs are available.
  • Returned values are type of ApiResponse and expose rate limit informaiton with GetRateLimit() method.
  • The folder structure of the project has been reorganized to follow Microsoft's recommendation.
  • Unit tests have been improved. They are smaller, more focused and have cleanup methods.
  • Added .NET 6.0 support.

The proper usage of the library:

var clientFactory = new StreamClientFactory("YourApiKey", "YourApiSecret");
// Note: all client instances can be used as a singleton for the lifetime
// of your application as they don't maintain state.
var userClient = clientFactory.GetUserClient();
var channelClient = clientFactory.GetChannelClient();
var messageClient = clientFactory.GetMessageClient();
var reactionClient = clientFactory.GetReactionClient();

var jamesBond = await userClient.UpsertAsync(new UserRequest { Id = "james_bond" });
var agentM = await userClient.UpsertAsync(new UserRequest { Id = "agent_m" });

var channel = await channelClient.GetOrCreateAsync("messaging", "superHeroChannel", createdBy: jamesBond.Id);
await channelClient.AddMembersAsync(channel.Type, channel.Id, jamesBond.Id, agentM.Id);

var message = await messageClient.SendMessageAsync(channel.Type, channel.Id, jamesBond.Id, "I need a new quest Agent M.");
await reactionClient.SendReactionAsync(message.Id, "like", agentM.Id);

⚙️ Installation

$ dotnet add package stream-chat-net

💡 Tip: you can find code samples in the samples folder.

✨ Getting started

Import

using StreamChat.Clients;

Initialize client

// Client factory instantiation.
var clientFactory = new StreamClientFactory("YourApiKey", "YourApiSecret");

// Or you can configure some options such as custom HttpClient, HTTP timeouts etc.
var clientFactory = new StreamClientFactory("YourApiKey", "YourApiSecret", opts => opts.Timeout = TimeSpan.FromSeconds(5));

// Get clients from client factory. Note: all clients can be used as a singleton in your application.
var channelClient = clientFactory.GetChannelClient();
var messageClient = clientFactory.GetMessageClient();

Generate a token for client-side usage

var userClient = clientFactory.GetUserClient();

// Without expiration
var token = userClient.CreateToken("bob-1");

// With expiration
var token = userClient.CreateToken("bob-1", expiration: DateTimeOffset.UtcNow.AddHours(1));

Create/Update users

var userClient = clientFactory.GetUserClient();

var bob = new UserRequest
{
    Id = "bob-1",
    Role = Role.Admin,
    Teams = new[] { "red", "blue" } // if multi-tenant enabled
};
bob.SetData("age", 27);

await userClient.UpsertAsync(bob);

// Batch update is also supported
var jane = new UserRequest { Id = "jane"};
var june = new UserRequest { Id = "june"};
var users = await userClient.UpsertManyAsync(new[] { bob, jane, june });

GDPR-like User endpoints

var userClient = clientFactory.GetUserClient();

await userClient.ExportAsync("bob-1");
await userClient.DeactivateAsync("bob-1");
await userClient.ReactivateAsync("bob-1");
await userClient.DeleteAsync("bob-1");

Channel types

var channelTypeClient = clientFactory.GetChannelTypeClient();

var chanTypeConf = new ChannelTypeWithStringCommands
{
    Name = "livechat",
    Automod = Automod.Disabled,
    Commands = new List<string> { Commands.Ban },
    Mutes = true
};
var chanType = await channelTypeClient.CreateChannelTypeAsync(chanTypeConf);

var allChanTypes = await channelTypeClient.ListChannelTypesAsync();

Channels

var channelClient = clientFactory.GetChannelClient();

// Create a channel with members from the start, Bob is the creator
var channel = channelClient.GetOrCreateAsync("messaging", "bob-and-jane", bob.Id, bob.Id, jane.Id);

// Create channel and then add members, Mike is the creator
var channel = channelClient.GetOrCreateAsync("messaging", "bob-and-jane", mike.Id);
channelClient.AddMembersAsync(channel.Type, channel.Id, bob.Id, jane.Id, joe.Id);

Messaging

var messageClient = clientFactory.GetMessageClient();

// Only text
messageClient.SendMessageAsync(channel.Type, channel.Id, bob.Id, "Hey, I'm Bob!");

// With custom data
var msgReq = new MessageRequest { Text = "Hi june!" };
msgReq.SetData("location", "amsterdam");

var bobMessageResp = await messageClient.SendMessageAsync(channelType, channel.Id, msgReq, bob.Id);

// Threads
var juneReply = new MessageRequest { Text = "Long time no see!" };
var juneReplyMessage = await messageClient.SendMessageToThreadAsync(channel.Type, channel.Id, juneReply, june.Id, bobMessageResp.Message.Id)

Reactions

var reactionClient = clientFactory.GetReactionClient();

await reactionClient.SendReactionAsync(message.Id, "like", bob.Id);

var allReactions = await reactionClient.GetReactionsAsync(message.Id);

Moderation

var channelClient = clientFactory.GetChannelClient();
var userClient = clientFactory.GetUserClient();
var flagClient = clientFactory.GetFlagClient();

await channelClient.AddModeratorsAsync(channel.Type, channel.Id, new[] { jane.Id });

await userClient.BanAsync(new BanRequest
{
    Type = channel.Type,
    Id = channel.Id,
    Reason = "reason",
    TargetUserId = bob.Id,
    UserId = jane.Id
});

await flagClient.FlagUserAsync(bob.Id, jane.Id);

Permissions

var permissionClient = clientFactory.GetPermissionClient();

await permissionClient.CreateRoleAsync("channel-boss");

// Assign users to roles (optional message)
await channelClient.AssignRolesAsync(new AssignRoleRequest
{
    AssignRoles = new List<RoleAssignment>
    {
        new RoleAssignment { UserId = bob.ID, ChannelRole = Role.ChannelModerator },
        new RoleAssignment { UserId = june.ID, ChannelRole = "channel-boss" }
    },
    Message = new MessageRequest { Text = "Bob and June just became mods", User = bob }
});

Devices

var deviceClient = clientFactory.GetDeviceClient();

var junePhone = new Device
{
    ID = "iOS Device Token",
    PushProvider = PushProvider.APN,
    UserId = june.ID
};

await deviceClient.AddDeviceAsync(junePhone);

var devices = await deviceClient.GetDevicesAsync(june.Id);

Export Channels

var channelClient = clientFactory.GetChannelClient();
var taskClient = clientFactory.GetTaskClient();

var taskResponse = channelClient.ExportChannelAsync(new ExportChannelRequest { Id = channel.Id, Type = channel.Type });

// Wait for the completion
var complete = false;
var iterations = 0;
AsyncTaskStatusResponse resp = null;
while (!complete && iterations < 1000)
{
    resp = await taskClient.GetTaskStatusAsync(taskResponse.TaskId);
    if (resp.Status == AsyncTaskStatus.Completed)
    {
        complete = true;
        break;
    }
    iterations++;
    await Task.Delay(100);
}

if (complete)
{
    Console.WriteLine(resp.Result["url"]);
}

✍️ Contributing

We welcome code changes that improve this library or fix a problem, please make sure to follow all best practices and add tests if applicable before submitting a Pull Request on Github. We are very happy to merge your code in the official repository. Make sure to sign our Contributor License Agreement (CLA) first. See our license file for more details.

Head over to CONTRIBUTING.md for some development tips.

🧑‍💻 We are hiring!

We've recently closed a $38 million Series B funding round and we keep actively growing. Our APIs are used by more than a billion end-users, and you'll have a chance to make a huge impact on the product within a team of the strongest engineers all over the world.

Check out our current openings and apply via Stream's website.

stream-chat-net's People

Contributors

andrew-tevent avatar bdandy avatar bogdan-d avatar bogdan-getstream avatar cconfer-livly avatar ferhatelmas avatar ffenix113 avatar github-actions[bot] avatar itsmeadi avatar link512 avatar marco-ulge avatar miagilepner avatar penghouho avatar peterdeme avatar ruggi avatar seniyg avatar sierpinskid avatar skaegebein avatar tbarbugli avatar thesyncim avatar tjkb avatar totalimmersion avatar vishalnarkhede avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

stream-chat-net's Issues

Xamarin / Maui support?

I'm testing various chat solutions for mobile apps and it looks like stream-chat-net is pretty much only intended to be used server-side, is that correct?

If so, are there plans or other options to provide what might be expected for a client-side experience? I'm thinking of things like:

  • Websocket-based / real-time client wrappers (I only see REST-based currently)
  • out-of-the-box UI kit

Parsing Error - EventType - channel.created

We have a .net backend listening event on the SQS integration

Through the SQS we are receiving messages with type

"type":"channel.created"

Throwing

var json = JObject.Parse(message.Body);
var chatEvent = Event.FromJObject(json);

Error reading string. Unexpected token: StartObject. Path 'config.commands[0]'.
   at Newtonsoft.Json.JsonReader.ReadAsString()
   at Newtonsoft.Json.JsonReader.ReadForType(JsonContract contract, Boolean hasConverter)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateList(IList list, JsonReader reader, JsonArrayContract contract, JsonProperty containerProperty, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateList(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)

After some investigation - it is not supported in the .net client

public struct EventType

Also not really mentioned in the doc
https://getstream.io/chat/docs/node/event_object

First question
why do we receive those channel.created via SQS ?

Second question
For now I just want to discard those messages
What is the best option ?

I did a filter based on the EventType
but if parser fails on the ChannelCreated event
I can not filter out properly

see below


        public static bool IsProcessable(this Event chatEvent)
        {
            // We dont support all type of messages
            // https://getstream.io/chat/docs/react/webhook_events/
            switch (chatEvent.Type)
            {
                case EventType.MessageNew:
                case EventType.MessageDeleted:
                case EventType.MessageUpdated:
                    return true;
            }
            return false;
        }

        public async Task ProcessMessage(QueueMessage message, CancellationToken cancellationToken)
        {
            try
            {
                var json = JObject.Parse(message.Body);
                var chatEvent = Event.FromJObject(json);

                if (chatEvent.IsProcessable())
                {
                    _log.LogDebug($"[ChatEventsWorker] Processing chat event of type [{chatEvent.Type}]");
                    var eventProcessor = _chatEventsHelper.GetEventProcessor(chatEvent.Type);
                    await eventProcessor.ProcessEvent(chatEvent);
                }
            }
            catch (Exception e)
            {
                _log.LogError(LoggingEvents.ChatEventProcessFailed, e, $"[ChatEventsWorker] Unable to process chat message because of error => {e.Message} - Body: {message.Body}");
            }
        }


thank in advance

gz#11352

Hard delete option missing from SDK

We assumed stream-chat-net is used to implement a server side client that can hard delete messages via message id.
But we found that

(

public async Task<Message> DeleteMessage(string messageID)
)
public async Task DeleteMessage(string messageID)
only accept one argument but not the second argument like we found in stream-chat-js

(https://github.com/GetStream/stream-chat-js/blob/f74e3f0d6986363c3b457e0e088e6d47c3f711c7/src/client.ts#L1861)
async deleteMessage(messageID: string, hardDelete?: boolean)

gz#6181

Include channel name in channel query API

Hi, I am trying to obtain a list of channels via the QueryChannelsAsync method.
The querying itself works just fine, but I can't find a way to view a channel's name in the ChannelGetResponse object.
Is there a workaround for this?

Ban user usage confusion

Hello Stream dev team,

I was using stream chat net in my latest web chat app, and wanted to use Ban and UnBan features.
So in the readme file as you documented there, BanUser only accepts 3 parameters unlike me it accepts 4 parameters the first one called "targetID" which I don't know what is this should be.

Anyone could guide me I would be thankful?

gz#6728

Event object is missing property for "thread_participant"

Hi, I'm using stream-chat-net to parse "reply' type messages in my webhook.

Events for message.new contain "thread_participant" property if the message type is a reply.

However, the StreamChat.Event class is missing this property and hence this information gets lost while parsing.

Here's an example of thread reply event that gets captured by webhook:

image

channel partial update support

Unless I'm missing something, it doesn't appear as though the sdk supports the partial update of a channel. My specific use case would be updating a custom data value.

gz#12073

How to export the channel in .Net

In the documentation for the .Net SDK (https://getstream.io/chat/docs/dotnet-csharp/exporting_channels/?language=csharp) there is a section for exporting channels but the code example is in javascript, and the client method for .Net doesn't have an exportChannel . Currently I cannot find any way to export the chat from a channel via back-end. Is there a way to do this? It is especially useful since you probably need to parse it to show that data in a meaningful way, is ChannelState.Messages an approximation of what the exportChannel does?

gz#13512

Receiving "api_key not provided" after 2.0.0 update

Hello, I am receiving the following error after the 2.0.0 update (including latest) StreamChat.Exceptions.StreamChatException: UpdateUsers failed with error: "api_key not provided"

I have downgraded to 1.1.1, and can confirm that the issue is not present in lower versions.

Code to replicate is below:

public async Task<IEnumerable<User>> CreateUsers(StreamCreateUser[] usersToCreate)
{
	var factory = new StreamClientFactory("KEY", "SECRET");
	var userClient = factory.GetUserClient();
	
	var result = await userClient.UpsertManyAsync(usersToCreate.Select(z => new UserRequest
	{
		Id = z.UserId,
		Role = Role.User,
		Name = $"{z.PreferredName ?? z.FirstName} {z.LastName}"
	}));
	return result?.Users.Select(z => z.Value);
}

I have not had a chance to debug this yet, but if I am doing something wrong, please let me know

When will v0.4.4 release be available via nuget?

@ferhatelmas I see you created a new release with multi location support which is awesome. Do you have an ETA on when this will be pushed to nuget?

Note:

  • One of our clients is currently prevented from going live due to privacy concerns.
  • We cant use the binary package as their internal policies only allow third party packages when installed via nuget.

Error converting value "deleted" to type 'StreamChat.Models.MessageRequestType'

We are using stream-chat-net v 2.3.0
we are receiving events from SQS integration

Since couple of weeks we are receiving a new value deleted for MessageRequestType
This new value triggers the following error when deserializing

Error converting value "deleted" to type 'StreamChat.Models.MessageRequestType'. Path 'message.type', line 1, position 326.

After checking the code in you .net client

public enum MessageRequestType

It might be related to latest change about system message
44e5cb4

This is a new value that we received from the events queue ...
What are the impacts ?
All delete events are failing ?
or just the system messages ?

Can you double check if the system message feature has a side effect on the deleted messages

thanks in advance

Users are able to see several last message in messaging and team channels they don't belong to

Hi!

We have an issue that any user (even if NOT a member of the particular messaging channel) is able to see that exact channel and at least several messages in it.
Also looks like there is an issue with applying permissions to that particular case:

  • I've tried using the default policy set, and it has shown me the last several messages (in each channel the number is distinct) and throws an access error when trying to get more messages
  • I've tried restricting permissions more and more and tried even disabling access to All roles entirely. But still, I see the same thing: all channels are visible, and the last set of messages are visible as well.

This is a privacy violation issue, as users could see messages that do not belong to their access scope (chats of other people Not including the user using that).

Current permissions are set to the following:
[ { "action": "Deny", "name": "deny all policy", "resources": [ "*" ], "roles": [ "*" ], "owner": false, "priority": 1 } ]

Request example:
POST https://chat-us-east-1.stream-io-api.com/channels?user_id=************&api_key=************&connection_id=************
{ "filter_conditions": { "type": "messaging" }, "sort": [ { "field": "has_unread", "direction": -1 }, { "field": "last_message_at", "direction": -1 } ], "state": true, "watch": true, "presence": false, "limit": 30 }

Response (cleaned up, in order not to include 4K lines long response, including personal data) None of the users in members is my user, and permissions are set to deny everything:
{ "channels":[... { "channel": { "id": "!members-ieHLMtf2IgHJ8FeCzIsBzhFviClk7HucKmxykBrnNz4", "type": "messaging", "cid": "messaging:!members-ieHLMtf2IgHJ8FeCzIsBzhFviClk7HucKmxykBrnNz4", "last_message_at": "2021-06-08T12:47:10.55206Z", "created_at": "2021-06-08T12:47:07.965299Z", "updated_at": "2021-06-08T12:47:07.965299Z", "created_by": { "id": "5deb6667-df00-4672-89c6-02600bc16d25", "role": "user", "created_at": "2021-01-21T12:46:50.88392Z", "updated_at": "2021-04-08T13:50:20.335871Z", "last_active": "2021-06-08T12:45:18.133931Z", "banned": false, "online": false, "teams": [ "1e033efd-577a-42c1-a36d-83a05bc0fab2" ], "name": "Emails7 Changer7", "image": "https://prodprtseafilestorastg.blob.core.windows.net/avatars/a99648b5-16d9-40d0-84cd-04cc842bc7bc" }, "frozen": false, "disabled": false, "member_count": 2, "config": { "created_at": "2021-11-03T18:06:24.291235Z", "updated_at": "2021-11-03T18:26:17.643261Z", "name": "messaging", "typing_events": true, "read_events": true, "connect_events": true, "search": true, "reactions": true, "replies": true, "quotes": true, "mutes": true, "uploads": true, "url_enrichment": true, "custom_events": true, "push_notifications": true, "message_retention": "infinite", "max_message_length": 5000, "automod": "disabled", "automod_behavior": "flag", "blocklist_behavior": "flag", "automod_thresholds": {}, "commands": [ { "name": "giphy", "description": "Post a random gif to the channel", "args": "[text]", "set": "fun_set" } ] }, "team": "1e033efd-577a-42c1-a36d-83a05bc0fab2", "own_capabilities": [ "search-messages", "send-typing-events" ], "hidden": false }, "messages": [ { "id": "5deb6667-df00-4672-89c6-02600bc16d25-121d81a3-43ec-4e85-b328-3dc8f9718cca", "text": "teewt", "html": "\u003cp\u003eteewt\u003c/p\u003e\n", "type": "regular", "user": { "id": "5deb6667-df00-4672-89c6-02600bc16d25", "role": "user", "created_at": "2021-01-21T12:46:50.88392Z", "updated_at": "2021-04-08T13:50:20.335871Z", "last_active": "2021-06-08T12:45:18.133931Z", "banned": false, "online": false, "teams": [ "1e033efd-577a-42c1-a36d-83a05bc0fab2" ], "image": "https://prodprtseafilestorastg.blob.core.windows.net/avatars/a99648b5-16d9-40d0-84cd-04cc842bc7bc", "name": "Emails7 Changer7" }, "attachments": [], "latest_reactions": [], "own_reactions": [], "reaction_counts": {}, "reaction_scores": {}, "reply_count": 0, "cid": "messaging:!members-ieHLMtf2IgHJ8FeCzIsBzhFviClk7HucKmxykBrnNz4", "created_at": "2021-06-08T12:47:10.55206Z", "updated_at": "2021-06-08T12:47:10.55206Z", "shadowed": false, "mentioned_users": [], "silent": false, "pinned": false, "pinned_at": null, "pinned_by": null, "pin_expires": null } ], "pinned_messages": [], "watcher_count": 2, "read": [ { "user": { "id": "bfc34d55-895b-47da-84e4-306f4e532a94", "role": "user", "created_at": "2020-12-10T14:20:38.887844Z", "updated_at": "2021-04-08T13:59:09.74671Z", "last_active": "2021-09-06T11:57:24.935509Z", "banned": false, "online": false, "teams": [ "1e033efd-577a-42c1-a36d-83a05bc0fab2" ], "image": "https://prodprtseafilestorastg.blob.core.windows.net/avatars/df96d4ad-e884-49f2-8032-70ce3caeb414", "name": "***** ******" }, "last_read": "2021-06-08T12:48:22.079512064Z", "unread_messages": 0 }, { "user": { "id": "5deb6667-df00-4672-89c6-02600bc16d25", "role": "user", "created_at": "2021-01-21T12:46:50.88392Z", "updated_at": "2021-04-08T13:50:20.335871Z", "last_active": "2021-06-08T12:45:18.133931Z", "banned": false, "online": false, "teams": [ "1e033efd-577a-42c1-a36d-83a05bc0fab2" ], "image": "https://prodprtseafilestorastg.blob.core.windows.net/avatars/a99648b5-16d9-40d0-84cd-04cc842bc7bc", "name": "***** ******" }, "last_read": "2021-06-08T12:49:11.379953664Z", "unread_messages": 0 } ], "members": [ { "user_id": "5deb6667-df00-4672-89c6-02600bc16d25", "user": { "id": "5deb6667-df00-4672-89c6-02600bc16d25", "role": "user", "created_at": "2021-01-21T12:46:50.88392Z", "updated_at": "2021-04-08T13:50:20.335871Z", "last_active": "2021-06-08T12:45:18.133931Z", "banned": false, "online": false, "teams": [ "1e033efd-577a-42c1-a36d-83a05bc0fab2" ], "name": "***** ******", "image": "https://prodprtseafilestorastg.blob.core.windows.net/avatars/a99648b5-16d9-40d0-84cd-04cc842bc7bc" }, "created_at": "2021-06-08T12:47:07.968832Z", "updated_at": "2021-06-08T12:47:07.968832Z", "banned": false, "shadow_banned": false, "role": "owner", "channel_role": "channel_member" }, { "user_id": "bfc34d55-895b-47da-84e4-306f4e532a94", "user": { "id": "bfc34d55-895b-47da-84e4-306f4e532a94", "role": "user", "created_at": "2020-12-10T14:20:38.887844Z", "updated_at": "2021-04-08T13:59:09.74671Z", "last_active": "2021-09-06T11:57:24.935509Z", "banned": false, "online": false, "teams": [ "1e033efd-577a-42c1-a36d-83a05bc0fab2" ], "image": "https://prodprtseafilestorastg.blob.core.windows.net/avatars/df96d4ad-e884-49f2-8032-70ce3caeb414", "name": "***** ******" }, "created_at": "2021-06-08T12:47:07.968832Z", "updated_at": "2021-06-08T12:47:07.968832Z", "banned": false, "shadow_banned": false, "role": "member", "channel_role": "channel_member" } ], "membership": null } ...], "duration": "40.49ms" }

Please resolve this issue ASAP.
Thanks.

ProgressRetail
APP ID: 98681

Teams support

Hello,

In reference to the docs on https://getstream.io/chat/docs/multi_tenant_chat/?language=c_sharp

While I can in fact enable multitenant mode using UpdateAppSettings, it seems that stream-chat-net does not yet support the "team" properties of users or channels.

Javascript equivalents:
client.updateUser({id, teams: ["red", "blue"]});
client.channel("messaging", "red-general", {team: "red"}).create()

Any way that these features can be added to the .NET library?

gz#7802

Parsing the webhook body

What is the recommended approach for parsing the webhook body into an object?
Currently I have this code in my webhook API controller:

var signature = request.Headers["X-Signature"];
if (!_client.VerifyWebhook(body, signature)) {
  throw new Exception("invalid signature");
}
var jsonBody = JsonConvert.DeserializeObject(body);

Looking at the StreamChat library code, it looks like the obvious thing I should do next is:
var webhookEvent = Event.FromJObject(jsonBody);
but this method is marked internal so it's not possible.

How are we supposed to achieve this?

message partial update support

Currently this SDK seems to only support UpdateMessage, which when used seems to clear all fields that are not supplied in the MessageInput (at least some of them, e.g. the message text is lost unless you supply it).

Could we please get a UpdateMessagePartial or similar?

Similar to #41

Channel being provisioned without a team/outside of a team

Hi, I am attempting to create a channel under a particular team but am not seeing the expected result.

Below is the code I am using:

var streamMembers = streamUserIdsToAdd.Select(z => new ChannelMember
{
    UserId = z,
});

var channelData = new ChannelRequest { CreatedBy = new UserRequest { Id = createdByUserId }, Members = streamMembers, Team = team };
var channelGetRequest = new ChannelGetRequest { Data = channelData };

await channelClient.GetOrCreateAsync("messaging", channelGetRequest);

A few things to note:

  1. The team definitely exists from previous user creation calls with the assigned
  2. The channel does get created, but is not assigned to a team (I am confirming this from the dashboard)
  3. The member assignment works perfectly
  4. We are using .NET Framework 472
  5. I used this as a sample from the documentation
    image

MessageModerationResult is returning a double but is declared as an integer.

Description

I'm getting a deserialization error while calling var result = await client.QueryMessageFlags(request);

Example of response:

  "flags": [
    {
      "created_by_automod": true,
      "moderation_result": {
        "message_id": "REMOVED_FOR_SCREENSHOT",
        "action": "flag",
        "moderated_by": "blocklist",
        "blocked_word": "shit",
        "blocklist_name": "profanity_list",
        "user_karma": 7.668420264835362,
        "user_bad_karma": false,
        "created_at": "2022-08-08T21:44:11.364371Z",
        "updated_at": "2022-08-08T21:44:11.364371Z"
      },
   }]

Error

---> Newtonsoft.Json.JsonReaderException: Input string '7.668420264835362' is not a valid integer. Path 'flags[0].moderation_result.user_karma', line 1, position 282.

What's need to be done

The property UserKarma need to be change to a double? instead of an int? in MessageModerationResult:

    public class MessageModerationResult
    {
        public string MessageId { get; set; }
        public string Action { get; set; }
        public string ModeratedBy { get; set; }
        public string BlockedWord { get; set; }
        public string BlocklistName { get; set; }
        public Thresholds ModerationThresholds { get; set; }
        public ModerationScore AiModerationResponse { get; set; }
        public int? UserKarma { get; set; }
        public bool? UserBadKarma { get; set; }
        public DateTimeOffset? CreatedAt { get; set; }
        public DateTimeOffset? UpdatedAt { get; set; }
    }

Channel ban user method deprecated?

Is this part of the documentation up to date?

//add a ban with a timeout
await chan.BanUser(june.ID, "Being a big jerk", 4);

I tried this recently and it throws an error, the method from the current nugget package has this signature: BanUser(string targetID, string id, string reason, int timeoutMinutes = 0);

I assume targetId is the user you want to ban, id is the user that is banning. I tried the method from the package with an id of an admin and a member to ban and it returns OK, but no changes are made to the member

Remove and add members can not pass initiator

The initiator that removed the member is ignored in the request to update channel.

This also leads to member.removed events (on SQS) not containing the initiator of the action.

In the code below initiatorId is ignored

var memberDeletedMessage = "some message";
var messageRequest = new MessageRequest() { 
    Type = MessageRequestType.System, 
    Text = memberDeletedMessage, 
    UserId = initiatorId 
};

await _streamClientFactory.GetChannelClient()
    .RemoveMembersAsync(channelType, channelId, new List<string> { memberToDeleteUserId }, messageRequest);

ChannelMember.User not including json properties

ChannelMember.User is using UserRequest therefore it does not include Online or DeactivatedAt. These values are present in the json payload and were present before the v1.0 data model refactor.

Can't Remove channel Member

Hello getstream team,

I'm facing trouble while removing a user from channel, fyi this user is the creator of the channel.

So previously I was able to leave the channel that I created normally now I find myself still a member in channel after removing my self from the channel.

Is there any business changes that changed the way of managing removing channel members?

@keyneston @gumuz @tbarbugli @pterk @tschellenbach @shodgetts @sirio7g

gz#6923

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.