Here's my code:
const provider = new WalletConnectProvider({
rpc: {
private-testnet-chainId: "private testnet",
},
qrcodeModalOptions: {
mobileLinks: [
"rainbow",
"metamask",
],
},
});
// Enable session (triggers QR Code modal)
await provider.enable();
const web3 = new Web3(provider);
However, I do not see the metamask option:
What am I missing here?
The mobileLinks array is specifically for mobile devices, and does not impact desktop usage or display. The QR code can be used to access Metamask on desktop.
Related
I'm trying to use the Shopify API to query all the orders of a selected Shopify store, using the private app instead of the OAUTH method. Below I have added the code, can't seem to figure out how to get it to work cause there isn't much documentation for the use of the private apps. Does anyone know how I can achieve this or has done this before? I think I maybe wrong but there maybe an error in creating the session.
Upon running the below code I get the below error:
Error: Missing adapter implementation for 'abstractRuntimeString' - make sure to import the appropriate adapter for your platform
const { shopifyApi, ApiVersion, Session, LATEST_API_VERSION } = require('#shopify/shopify-api');
const { randomUUID } = require('crypto');
const { restResources } = require('#shopify/shopify-api/rest/admin/2022-10');
const selectedStore = {
shop: "store.myshopify.com",
api_secret: "",
api_key: "",
private_admin_key: ""
};
const shopify = shopifyApi({
apiKey: selectedStore.api_key,
apiSecretKey: selectedStore.api_secret,
scopes: ['read_orders', 'read_analytics', 'read_customers'],
hostName: '<ngrok_url>',
apiVersion: LATEST_API_VERSION,
isEmbeddedApp: false,
isPrivateApp: true,
restResources
});
const session = new Session({
id: randomUUID(),
state: 'state',
shop: selectedStore.shop,
accessToken: selectedStore.private_admin_key,
isOnline: true,
})
console.log(session)
const getOrders = async () => {
const orders = await shopify.rest.Order.all({
session,
status: "all"
})
return orders
}
getOrders()
If you have a Auth Token from a private App (inside the Shopify Admin), with permissions to read orders, you make a call to the Shopify store using that token. Look up the end point you call. Formulate your call. Make a GET or POST. Nothing hard to do there. Shopify assumes you know how to make a GET request with JS. Provide the Auth Token you gave yourself, and you'll get back all the orders you asked for. You cannot skip out on learning paging etc.. but again, that is also pretty standard stuff not special to Shopify.
I am trying to initialize a new chat using a devToken to allow client-side generated tokens by coding the following inside an async function:
let chatClient = await new StreamChat(apiKey);
await chatClient.updateAppSettings({
disable_auth_checks: true,
});
await chatClient.setUser(
{
id: 'user-0',
name: random-user-name,
},
chatClient.devToken('user-0'),
);
but am getting the error that "Both secret and user tokens are not set", despite using a devToken. The error stops the code from running once it hits
await chatClient.updateAppSettings({
disable_auth_checks: true,
});
, which is supposed to allow me to use the .devToken in place of a userToken.
So I added my secretKey to new StreamChat
let chatClient = await new StreamChat(apiKey, secretKey);
however, then I get the error "TypeError: Cannot read property 'sign' of null at JWTServerToken" right after that line runs.
And if I try to generate a userToken and replace chatClient.devToken('user-0') with userToken like this
let userToken = await chatClient.createToken("user-0");
I get the error "Error: tokens can only be created server-side using the API Secret", which is what I was trying to avoid.
Does anyone know how to correctly enable .devTokens so that the chatClient can be set without generating a token server-side?
Thanks!
This needs to be done via the dashboard. First, make sure your app is in development mode.
Then, navigate to the app's chat overview page and enable "Disable Auth Checks". Hit save.
So,
I searched far and wide, read everything I could find on the topic and I am still failing at this. I have managed to send proactive message to user, reply to a topic in team, etc. but I am unable to send a proactive message (create new post) in a team channel.
Is there an available example (I was unable to find any)? MS Docs for NodeJS seem to show an example of messaging each user in the team, but not the channel itself.
I explored the source code, and channelData is hardcoded to null inside botFrameworkAdapter.js, which only adds to the confusion.
So, basic code is:
const builder = require('botbuilder');
const adapter = new builder.BotFrameworkAdapter({
appId: 'XXX',
appPassword: 'YYY'
});
const conversation = {
channelData: {
//I have all this (saved from event when bot joined the Team)
},
...
// WHAT THIS OBJECT NEEDS TO BE TO SEND A SIMPLE "HELLO" TO A CHANNEL?
// I have all the d
};
adapter.createConversation(conversation, async (turnContext) => {
turnContext.sendActivity('HELLO'); //This may or may not be needed?
});
Has anyone done this with Node ? If so, can anyone show me a working example (with properly constructed conversation object)?
* EDIT *
As Hilton suggested in the answer below, I tried using ConnectorClient directly, but it returns resource unavailable (/v3/conversations)
Here is the code that I am using (it's literally only that, just trying to send demo message):
const path = require('path');
const { ConnectorClient, MicrosoftAppCredentials } = require('botframework-connector');
const ENV_FILE = path.join(__dirname, '.env');
require('dotenv').config({ path: ENV_FILE });
const serviceUrl = 'https://smba.trafficmanager.net/emea/';
async function sendToChannel() {
MicrosoftAppCredentials.trustServiceUrl(serviceUrl);
var credentials = new MicrosoftAppCredentials(process.env.MicrosoftAppId, process.env.MicrosoftAppPassword);
var client = new ConnectorClient(credentials, { baseUri: serviceUrl });
var conversationResponse = await client.conversations.createConversation({
bot: {
id: process.env.MicrosoftAppId,
name: process.env.BotName
},
isGroup: true,
conversationType: "channel",
id: "19:XXX#thread.tacv2"
});
var acivityResponse = await client.conversations.sendToConversation(conversationResponse.id, {
type: 'message',
from: { id: process.env.MicrosoftAppId },
text: 'This a message from Bot Connector Client (NodeJS)'
});
}
sendToChannel();
What am I doing wrong?
Okay, so, this is how I made it work. I am posting it here for future reference.
DISCLAIMER: I still have no idea how to use it with botbuilder as was asked in my initial question, and this answer is going to use ConnectorClient, which is acceptable (for me, at least). Based on Hilton's directions and a GitHub issue that I saw earlier ( https://github.com/OfficeDev/BotBuilder-MicrosoftTeams/issues/162#issuecomment-434978847 ), I made it work finally. MS Documentation is not that helpful, since they always use context variable which is available when your Bot is responding to a message or activity, and they keep a record of these contexts internally while the Bot is running. However, if your Bot is restarted for some reason or you want to store your data in your database to be used later, this is the way to go.
So, the code (NodeJS):
const path = require('path');
const { ConnectorClient, MicrosoftAppCredentials } = require('botframework-connector');
const ENV_FILE = path.join(__dirname, '.env');
require('dotenv').config({ path: ENV_FILE });
const serviceUrl = 'https://smba.trafficmanager.net/emea/';
async function sendToChannel() {
MicrosoftAppCredentials.trustServiceUrl(serviceUrl);
var credentials = new MicrosoftAppCredentials(process.env.MicrosoftAppId, process.env.MicrosoftAppPassword);
var client = new ConnectorClient(credentials, { baseUri: serviceUrl });
var conversationResponse = await client.conversations.createConversation({
bot: {
id: process.env.MicrosoftAppId,
name: process.env.BotName
},
isGroup: true,
conversationType: "channel",
channelData: {
channel: { id: "19:XXX#thread.tacv2" }
},
activity: {
type: 'message',
text: 'This a message from Bot Connector Client (NodeJS)'
}
});
}
sendToChannel();
NOTE: As Hilton pointed out, serviceUrl also needs to be loaded from your database, along with the channel id. It is available inside the activity which you receive initially when your Bot is added to team / channel / group along with channelId which you will also need, and you need to store those for future reference (do not hardcode them like in the example).
So, there is no separate createConversation and sendActivity, it's all in one call.
Thanks Hilton for your time, and a blurred image of my hand to MS Docs :)
Hope this helps someone else
(I'm replacing my previous answer as I think this fits the situation much better).
I've looked more into this and done a Fiddler trace to get you a more complete answer. I'm not a Node guy, so I'm not sure this will translate 100%, but let's see.
Basically, you're wanting to send to the following endpoint:
https://smba.trafficmanager.net/emea/v3/conversations/19:[RestOfYourChannelId]/activities
and you'll be posting a message like the following:
{
"type": "message",
"from": {
"id": "28:[rest of bot user id]",
"name": "[bot name]"
},
"conversation": {
"isGroup": true,
"conversationType": "channel",
"id": "19:[RestOfYourChannelId]"
},
"text": "Test Message"
}
However, to post to that endpoint, you need to authenticate to it properly. It's possible to do that, and communicate with the endpoint directly, but it's actually easier to just use the built-in mechanisms. This means getting and storing the conversationreference when the bot is first installed to the channel. This file shows how to do that (see how it gets and stores the conversationReference in the this.onConversationUpdate function). In that same sample, in a different file, it shows how to use that conversation reference to actually send the pro-active message - see here, where it uses adapter.continueConversation.
One of the Microsoft bot team members also shows this in similar detail over here. He also adds MicrosoftAppCredentials.trustServiceUrl(ref.serviceUrl); which can be necessary under certain circumstances (if you're having security issues, give that a try).
That -should- cover what you need, so give it a go, and let me know if you're still having difficulties.
I would like to have a very simple client in nodejs (an example) that can receive messages from my contacts in telegram. I just searched in internet but I only get bot samples. I want to receive group messages in what I don't have access to give privileges to my bot so I would like to know if I can receive my own messages with no bot as intermediary.
Well... Other answers give examples from unmaintained libraries. Hence, you should not rely on these libraries.
See: telegram.link is dead
You should use the newest Telegram client library which is telegram-mtproto
1. Obtain your api_id and api_hash from:
Telegram Apps
2. Install the required client library:
npm install telegram-mtproto#beta --save
3. Initialize your node.js application with api_id and api_hash you got from Telegram Apps and with your phone number:
import MTProto from 'telegram-mtproto'
const phone = {
num : '+90555555555', // basically it is your phone number
code: '22222' // your 2FA code
}
const api = {
layer : 57,
initConnection : 0x69796de9,
api_id : 111111
}
const server = {
dev: true //We will connect to the test server.
} //Any empty configurations fields can just not be specified
const client = MTProto({ server, api })
async function connect(){
const { phone_code_hash } = await client('auth.sendCode', {
phone_number : phone.num,
current_number: false,
api_id : 111111, // obtain your api_id from telegram
api_hash : 'fb050b8fjernf323FDFWS2332' // obtain api_hash from telegram
})
const { user } = await client('auth.signIn', {
phone_number : phone.num,
phone_code_hash: phone_code_hash,
phone_code : phone.code
})
console.log('signed as ', user);
}
connect();
4. Receive messages (The fun part! 👨🏻💻)
const telegram = require('./init') // take a look at the init.js from the examples repo
const getChat = async () => {
const dialogs = await telegram('messages.getDialogs', {
limit: 50,
})
const { chats } = dialogs;
const selectedChat = await selectChat(chats);
return selectedChat;
}
Furthermore, Take a look at the examples from the original repo:
Usage Examples
Reading Chat History
Updating Profile Info
If you want to interact with Telegram data outside one of the official applications (website, mobile or desktop app etc...) you will have to create an App, so you will be required to generate API key and/or use any already existing App which fit your requirement (bots in your case).
Let me underline that with API system it appear difficult to get access to something which is restricted, if you don't have previously grant or add privileges to access it ... Nobody want that anyone could access any data...
Regards
You can use the following libraries.
https://github.com/zerobias/telegram-mtproto
https://github.com/dot-build/telegram-js
They provide abstractions to build applications to interact with telegram. for an example on how to use telegram-js, you can use https://github.com/dot-build/telegram-js/blob/master/sample.js.
(Thank you #gokcand for the feedback)
Clearly by the negative score, I haven't provided enough information - sorry about that. However, perhaps add comments to explain why rather than just marking it down?
2nd attempt at a description:
I would like to be able to connect to Spotify's web API interface (https://developer.spotify.com/web-api/) on a headless embedded platform (Arm based simple MCU with WiFi). The username and password would be hardcoded into the system, probably added at setup time with the help of a mobile device (providing a temporary user interface).
I want to be able to add tracks to a playlist, which requires an authentication token. Spotify's usual flow requires the embedded platform to host their webpage login, as described here (https://developer.spotify.com/web-api/authorization-guide/).
Is this possible to authenticate without the webpage?
I have seen here (https://developer.spotify.com/technologies/spotify-ios-sdk/token-swap-refresh/) that Spotify recommend mobile apps use a remote server to handle refreshing of tokens - perhaps that's a route?
Any pointers would be appreciated.
I don't think it is bad question. I am also working on a headless player that runs on a local network which makes the authorization flow a bit awkward. So this is not much of an answer, but let me explain how it can be done.
Your headless system needs to have a web interface that can redirect to the spotify authorization url and handle the callback. The problem is that you have to register the callback url on your spotify app. Say you register http://server1/spotify/auth/callback. Now the server1 needs to be accessible from the device doing the authorization, f.ex by adding it to /etc/hosts.
The good news is that refresh can be done without user intervention, so if you store the access token the user will only need to do this one time after installing.
I know that this is really late, but for anyone having the same issue...
I am working on something similar was mentioned above so I'll share what I know. I am creating a music player that could act as another device on my Spotify (using: https://developer.spotify.com/documentation/web-playback-sdk/) account as well be controlled by my custom webpage.
I have 3 parts to this: backend server, the SDK player webpage (for me: http://localhost:8080/#/pup/player), the frontend UI webpage
(all the code snippets are a part of a class)
The only way I was able to get it running was like so:
Start the backend server and initialize puppeteer
async initPup(){
this.browser = await puppeteer.launch({
headless: false, // This is important, because spotify SDK doesn't create the device when using headless
devtools: true,
executablePath: "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe", //I also have to use Chrome and not Chromium, because Chromium is missing support for EME keySystems (yes, I've tried bruteforcing chromium versions or getting Firefox to work using createBrowserFetcher())
ignoreDefaultArgs: ['--mute-audio'],
args: ['--autoplay-policy=no-user-gesture-required']
});
this.page = (await this.browser.pages())[0]; // create one page
if(this.page == undefined){
this.page = await this.browser.newPage();
}
this.pup_ready = true;
console.log(await this.page.browser().version())
}
Open your SDK player page with puppeteer and pass the ClientID and ClientSecret of your Spotify project (https://developer.spotify.com/dashboard/):
async openPlayer(){
// const player_page = "http://localhost:8080/#/pup/player"
if(this.pup_ready){
await this.page.goto(player_page + "/?&cid=" + this.client_id + "&csec=" + this.client_secret);
}
}
On the SDK player webpage save the cid and csec URL params to LocalStorage. This should be done when no ULR parameter named "code" has been given, because that's the authorizations code which will be generated in the next step.
Something like:
var auth_code = url_params_array.find(x=>x.param.includes("code")); // try to get the auth code
var c_id = url_params_array.find(x=>x.param.includes("cid")); //get cid
var c_sec = url_params_array.find(x=>x.param.includes("csec")); //get csec
var token = undefined;
if(auth_code == undefined){ // the auth code is not defined yet and it has to be created
//SAVING CLIENT ID and CLIENT SECRET
c_id = c_id.value;
c_sec = c_sec.value;
window.localStorage.setItem("__cid", c_id)
window.localStorage.setItem("__csec", c_sec)
//GETTING THE AUTH CODE
var scope = "streaming \
user-read-email \
user-read-private"
var state = "";
var auth_query_parameters = new URLSearchParams({
response_type: "code",
client_id: c_id,
scope: scope,
redirect_uri: "http://localhost:8080/#/pup/player/",
state: state
})
window.open('https://accounts.spotify.com/authorize/?' + auth_query_parameters.toString()); // tak the puppeteer to the spotify login page
}
Login on the spotify page using your credential to create the auth token. I had to use https://www.npmjs.com/package/puppeteer-extra-plugin-stealth to bypass CAPTCHAS
async spotifyLogin(mail="<YOUR_SPOTIFY_MAIL>", pass = "<YOUR_SPOTIFY_PASSWORD") {
var p = this.page = (await this.browser.pages())[1] // get the newly opened page with the spotify
//await p.waitForNavigation({waitUntil: 'networkidle2'})
await p.focus("#login-username"); // put in the credentials
await p.keyboard.type(mail);
await p.focus("#login-password");
await p.keyboard.type(pass);
await p.$eval("#login-button", el => el.click());
(await this.browser.pages())[0].close(); // close the old SDK page
await sleep(1000) // wait to be redirected back to your SDK page
//
this.page = (await this.browser.pages())[0];
this.auth_code = await this.page.evaluate( (varName) => window.localStorage.getItem(varName), ["__auth"] ) // here is ave the auth token as a property of the class instance as well
}
Once you're redirected to SDK page again you already have cid and csec and now also the auth token.
if(auth_code == undefined)
//... (this is already in step 3)
}else{
// GETTING CID and C SECRET AGAIN
c_id = window.localStorage.getItem("__cid")
c_sec = window.localStorage.getItem("__csec")
// SAVING THE AUTH CODE
auth_code = auth_code.value;
window.localStorage.setItem("__auth", auth_code)
}
Generate a token on the backend.
async genToken():Promise<void>{
//Pretty much coppied from: https://developer.spotify.com/documentation/web-playback-sdk/guide/
var authOptions = {
url: 'https://accounts.spotify.com/api/token',
headers: {
'Authorization': 'Basic ' + (Buffer.from(this.client_id + ':' + this.client_secret).toString("base64"))
},
form: {
code: this.auth_code,
redirect_uri: "http://localhost:8080/#/pup/player/",
grant_type: 'authorization_code'
},
json: true
};
var token;
var refresh_token;
await request.post(authOptions, function(error, response, body) { // also get the refresh token
if (!error && response.statusCode === 200) {
token = body.access_token;
refresh_token = body.refresh_token;
}
});
while (!token && !refresh_token){ // wait for both of them
await sleep(100)
}
this.token = token; // save them in the class instance properties
this.refresh_token = refresh_token;
}
Lastly the puppeteer fills in a html field with the token generated in step 6 on the SDK site and presses a button to start the SDK player.
// this function gets called after the button gets pressed
async function main(){
console.log(window.localStorage.getItem("__cid")) // print out all the data
console.log(window.localStorage.getItem("__csec"))
console.log(window.localStorage.getItem("__auth"))
console.log(getToken())
const player = new Spotify.Player({ // start the sporify player
name: 'Home Spotify Player',
getOAuthToken: cb => cb(getToken())
});
player.connect().then(()=>{ // connect the player
console.log(player)
});
window.player = player;
}
function getToken(){
return document.getElementById("token_input").value;
}
You are done. Next step for me at least was communicating using another UI page to the backend puppeteer to control the SDK page (play/pause/skip etc.) This process is pretty "hacky" and not pretty at all but if you just have a little personal project it should do the job fine.
If anyone would be interested in the whole code I might even upload it somewhere, but I think this read is long-enough and overly detailed anyway.
The proper way for this would be to use the device authorization grant flow - Spotify does this already for its TV applications, but they seem to block other applications from using it. It is possible to find clientIds online that are working with this, but it is not supported by Spotify.
I explained how this works and requested that they enable it in a supported way for custom applications in this feature request - please upvote the idea there if you find it useful.
That said, it is also possible to implement your own device authorization grant flow by hosting an extra server between your device and Spotify. That server should
host an authorize and a token API endpoint
host a user-facing page where the user can enter the user code
a callback page for Spotify to redirect the user after login
I believe this is how https://github.com/antscode/MacAuth implements it:
When the device calls the authorize, the server should generate a record containing the device_code and user_code and send them back in the response. The server should keep the record for later.
When the user enters the user_code in the user-facing page, the server should redirect the user to Spotify to login, and after login the user should be redirected to the server's callback page. At that moment the server can fetch credentials from Spotify's token endpoint using the data it received in the callback. The server should store the credentials it received in the record of the user_code.
The device can poll the server using the device_code for the availability of the tokens using the token endpoint.