So I making a discord Bot and for some Reason I can't see the slash command I created.
Slash command
[SlashCommand("ping", "Receive a ping message")]
public async Task HandlePingCommand()
{
await RespondAsync("Stop pinging me!");
}
I'm almost sure it has something to do with the bots permissions.
I have set the GatewayIntents AllUnprivileged and MessageContent.
Discord Developer Portal Permissions
Added Information
if (IsDebug())
await sCommands.RegisterCommandsToGuildAsync("my server id"));
else
await sCommands.RegisterCommandsGloballyAsync(true);
I also added the applications.commands scope
If any more information and / or code is need I'll ofcourse add it.
Related
I am building a chatbot for Teams where the bot needs to connect to graph on behalf of the user. I'm working in C# with BotFramework v3 (for business reasons I cannot move to v4), my BotBuilder package is on version 3.20.1.
The problem: On Webchat, no problem, the bot displays the sign in card, I get redirected to a login page. When logged in, I get the magic number, which I paste into my bot and everything is fine.
On Teams, however, I click on the button, get directed to the login page and once logged in, the tab closes, no magic number and the channel doesn't get anything.
Here is what is configured:
Permissions:
The AAD v2 connection to my Azure app:
My valid domains in the teams manifest:
I've also changed my sign in button to an open url button when in Teams channel as it is a problem mentioned here https://github.com/microsoft/botframework-sdk/issues/2104 (and indeed sign in button doesn't react).
The code:
public override async Task StartAsync(IDialogContext context)
{
var token = await context.GetUserTokenAsync(ConnectionName).ConfigureAwait(false);
var oauthToken = context.Activity.ChannelData.oauthToken?.Value as string;
if (!string.IsNullOrWhiteSpace(oauthToken))
await DoThingsWithToken(context, oauthToken);
else
context.Call(await CreateGetTokenDialog(context), DoThingsWithToken);
}
private async Task<GetTokenDialog> CreateGetTokenDialog(IDialogContext context)
{
return new GetTokenDialog(
ConnectionName,
$"Please sign in to {ConnectionName} to proceed.",
"Sign In",
2,
"Hmm. Something went wrong, let's try again.");
}
private async Task DoThingsWithToken(IDialogContext context, IAwaitable<GetTokenResponse> tokenResponse)
{
var token = (await tokenResponse).Token;
// Do stuff...
}
I've looked online, but couldn't find any doc for SDK v3 anymore, nor people having this exact issue. Could anyone point me if it's a config problem, SDK version problem, or something else? And how to fix it?
[Edit] The documentation followed to configure the Teams SSO: https://learn.microsoft.com/en-us/microsoftteams/platform/sbs-bots-with-sso
Thank you, Best regards.
I want to create a private channel with my bot that only administrator roles have access to.
I have read through this article on how to let your bot create a private channel specific roles can view/join.
As of now discord has a feature where you can skip the roles step completely and just let all administrator roles view it.
Is there a way to do this in discord.net C#?
Here is my code of creating the channel:
var channel = Context.Guild.Channels.SingleOrDefault(x => x.Name == "log");
if (channel == null) // there is no channel with the name of 'log'
{
// create the channel
var newChannel = await Context.Guild.CreateTextChannelAsync("log");
// If you need the newly created channels id
var newChannelId = newChannel.Id;
await ReplyAsync("Created channel ``'log'``");
}
else // reply that the channel already exists
{
await ReplyAsync("Unable to create channel ``log`` channel already exists.");
}
Keep in mind this is not a duplicate as the other question mentions adding roles which can view the channel and not just skipping it like it is possible when manually creating a channel in discord.
log reffers to a text channel, Discord.net NuGet package version 2.1.1, Compiling for debug 32-bit with Visual Studio 2019 latest as of now.
Worked for me with:
SocketGuild guild = Bot.GetGuild(123456789012345678);
RestTextChannel newChannel = await guild.CreateTextChannelAsync("test-log");
await newChannel.AddPermissionOverwriteAsync(guild.EveryoneRole, OverwritePermissions.DenyAll(newChannel));
In fact that users with Administrative privilege can access any channel on the server, we can simply overwrite channel permissions after creation with DenyAll.
We have a bot design in Bot framework-4 using .Net c# sdk. This bot is hosted on IIS and available
on different channel such as Directline, MS Teams etc. We want to send proactive messages to all the user in MS teams to notify them irrespective of if they communicated with bot or not. The Proactive messages will be 1:1 message.
After doing lot of R&D we found that we will be only able to send Proactive message to user only when there conversation reference is present. (let me know if other way is also possible.)
Using below link and Sample to send Proactive message to user:
Proactive Message Sample
Document Referred
We are using cosmos DB container and auto save middleware for bot conversation state and user state management.
Code in ConfigureServices method of Startup.cs file:
var blobDbService = botConfig.Services.FirstOrDefault(s => s.Type == ServiceTypes.BlobStorage) ?? throw new Exception("Please configure your Blob service in your .bot file.");
var BlobDb = blobDbService as BlobStorageService;
var dataStore = new AzureBlobStorage(BlobDb.ConnectionString, BlobDb.Container);
var userState = new UserState(dataStore);
var conversationState = new ConversationState(dataStore);
services.AddSingleton(dataStore);
services.AddSingleton(userState);
services.AddSingleton(conversationState);
services.AddSingleton<ConcurrentDictionary<string, ConversationReference>>();
services.AddSingleton(new BotStateSet(userState, conversationState));
services.AddBot<EnterpriseTiBOT>(options =>
{
// Autosave State Middleware (saves bot state after each turn)
options.Middleware.Add(new AutoSaveStateMiddleware(userState, conversationState));
}
Code to Store Conversation Reference for each user:
private void AddConversationReference(Activity activity)
{
var conversationReference = activity.GetConversationReference();
_conversationReferences.AddOrUpdate(conversationReference.User.Id, conversationReference, (key, newValue) => conversationReference);
}
protected override async Task OnStartAsync(DialogContext dc, CancellationToken cancellationToken = default(CancellationToken))
{
AddConversationReference(dc.Context, cancellationToken);
}
Code in notifyContoller is same as the code from GitHub Sample. There are 2 issues we are facing :
The concurrent dictionary having conversation reference become blank when the IIS pool is recycled and we are not able to send the proactive message to the user, how to store it in Blob storage and access the same in Notify controller?
We want to send proactive message to all the user whether they have communicated with bot or not, any way to achieve this? Tried 3rd approach from this article. But the challenge is, we are not able to send message to user based on User ID or user principle name.
There are multiple ways to store the conversation and user info. You should store these details in more persistent place rather than in memory. Here is a sample app code which stores user detail and along with the conversation Id in cosmos DB at the time of installation of the app. You could look into the implementation part. It can be any storage (blob, SQL).
For sending proactive message, User must have access to your app. You could make your app install for everyone in the tenant from Teams admin portal. Here is a reference documentation for managing the app from admin portal.
You need to have the conversation ID (between a bot and user) for sending a proactive message. And the conversation Id is created when the bot is installed for an user Or in team/group where user is part of.
I want to add comment to the answer but I do not have enough reputation to do so. Just to eleborate point 1 , if you want to ask where can we get and save the conversation refences, you can get it via method named: OnConversationUpdateActivityAsync.
It took me some time to get to this, so I think it is useful to share.
You can get a lot of information eg user ID, channel ID from the activity, here is some sample code:
public class ProactiveBot : ActivityHandler
{
...
...
protected override Task OnConversationUpdateActivityAsync(ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
{
var conversationReferences = turnContext.Activity.GetConversationReference();
//this is your user's ID
string userId = conversationReference.User.Id;
//this is the bot's ID and will be the same for all activities under same bot.
string botId = conversationReference.Bot.Id;
...
...
...
}
}
I am creating a UWP application and I want to use the Onedrive API so that users can save a copy of their files in their Onedrive account, but I don't get it, so far I have only managed to login what I want is:
upload files
download files
and synchronize if any of them is modified
Create folders
Delete Files
This code achieves the login, but I can not move beyond this, as would proceed for upload files or download them
private async void btn_Login_Click(object sender, RoutedEventArgs e)
{
if (this.oneDriveClient == null)
{
try
{
// Setting up the client here, passing in our Client Id, Return Url,
// Scopes that we want permission to, and building a Web Broker to
// go do our authentication.
this.oneDriveClient = await OneDriveClient.GetAuthenticatedMicrosoftAccountClient(
clientId,
returnUrl,
scopes,
webAuthenticationUi: new WebAuthenticationBrokerWebAuthenticationUi());
// Show in text box that we are connected.
txtBox_Response.Text = "We are now connected";
// We are either just autheticated and connected or we already connected,
// either way we need the drive button now.
btn_GetDriveId.Visibility = Visibility.Visible;
}
catch (OneDriveException exception)
{
// Eating the authentication cancelled exceptions and resetting our client.
if (!exception.IsMatch(OneDriveErrorCode.AuthenticationCancelled.ToString()))
{
if (exception.IsMatch(OneDriveErrorCode.AuthenticationFailure.ToString()))
{
txtBox_Response.Text = "Authentication failed/cancelled, disposing of the client...";
((OneDriveClient)this.oneDriveClient).Dispose();
this.oneDriveClient = null;
}
else
{
// Or we failed due to someother reason, let get that exception printed out.
txtBox_Response.Text = exception.Error.ToString();
}
}
else
{
((OneDriveClient)this.oneDriveClient).Dispose();
this.oneDriveClient = null;
}
}
}
}
I created a sample repository in github:Onedrive Sync Files Sample
I have already tried using Dropbox, Gdrive, but its implementation for UWP seems to be much more complex, so I chose OneDrive. any answer will be very helpful thanks in advance
How to Sync files with OneDrive API in C#
For using OneDrive, we suggest you implement OneDrive feature with OneDrive Service that is part of Windows Community Toolkit .
Getting Started
To use the OneDrive API, you need to have an access token that authenticates your app to a particular set of permissions for a user. In this section, you'll learn how to:
Register your application to get a client ID and a client secret.
Sign your user in to OneDrive with the specified scopes using the token flow or code flow.
Sign the user out (optional).
And this is official code sample that you could refer.
I'm trying to implement authentication in BOT using OAuthPrompt in an WaterFallDialog class which contains 2 steps:
Calls the OathPrompt which provides sign in button to provide credentials
Gets the token, based on token retrieval success message is displayed and user is navigated to another dialog or else failure message is displayed with
user to re-prompt with login
Issue: I have to make user to navigate the user automatically to step#2 without any manual intervention upon successful validation.
Current Situation: I'm unable to do it as I have to type something to make user to navigate to step#2
Problem in: Emulator and Webchat channel
Language: C#
Bot SDK: V4
This is a new BOT i am trying to build as based on authentication i am displaying other options i.e. navigating user to another dialog for performing other options.
I have already tried using below in STEP#1:
stepContext.NextAsync()
This did not work, i had to eventually type something to navigate and more over it gave an exception invalid step index.
I have also tried by providing the index number which also did not work along with Cancellation token
Expected Result: User to navigate automatically to step#2 upon successful authentication using OAUTH Prompt
Actual Result: Not able to navigate it until typed anything
Adding code Below:
public class LoginDialog : WaterfallDialog
{
public LoginDialog(string dialogId, IEnumerable<WaterfallStep> steps = null)
: base(dialogId, steps)
{
AddStep(async (stepContext, cancellationToken) =>
{
await stepContext.Context.SendActivityAsync("Please login using below option in order to continue with other options, if already logged in type anything to continue...");
await stepContext.BeginDialogAsync(EchoWithCounterBot.LoginPromptName, cancellationToken: cancellationToken); // This actually calls the dialogue of OAuthPrompt whose name is is in EchoWithCounterBot.LoginPromptName.
return await stepContext.NextAsync(); // It comes here throws the error as explained above but also i have to type for it to navigate to below step
});
AddStep(async (stepContext, cancellationToken) =>
{
Tokenresponse = (TokenResponse)stepContext.Result;
if (Tokenresponse != null)
{
await stepContext.Context.SendActivityAsync($"logged in successfully... ");
return await stepContext.BeginDialogAsync(DisplayOptionsDialog.Id); //Here it goes To another dialogue class where options are displayed
}
else
{
await stepContext.Context.SendActivityAsync("Login was not successful, Please try again...", cancellationToken: cancellationToken);
await stepContext.BeginDialogAsync(EchoWithCounterBot.LoginPromptName, cancellationToken: cancellationToken);
}
return await stepContext.EndDialogAsync();
});
}
public static new string Id => "LoginDialog";
public static LoginDialog Instance { get; } = new LoginDialog(Id);
}
BeginDialogAsync or PromptAsync should always be the last call in a step, so you'll need to get rid of NextAsync. OAuthPrompt.BeginDialogAsync is special because you don't know if it's going to end the turn or not. If there's already an available token then it will return that token and automatically continue the calling dialog, which would be the next step in your case. If there's no token available then it will prompt the user to sign in, which needs to be the end of the turn. Clearly in that case it makes no sense to continue to the next step before giving the user a chance to sign in.
Other than that, your code should work. Please update both your Bot Builder packages and your Emulator to the latest versions (currently 4.4.3 for Bot Builder and 4.4.0 for Emulator). The Emulator should continue to the next step automatically when you sign in, but Web Chat will likely require the user to enter a magic code.
EDIT: If you are using a version of Emulator that does not handle automatic sign-ins correctly, you can configure Emulator to use a magic code instead in the settings.