I know it's possible to create a button to start a conversation for a number.
But is it possible to check first if this number has whatsapp?
I need a grid with multiple numbers, and show the option to start conversation only for numbers that have whatsapp.
Note: I want to make this process logged in to whatsapp web.
It is a bit old question, but i get this question when i search for the same thing. After some reads, this is what i get. Hope it could help someone that search the same thing.
You could use the Client.getNumberId() function to check if the mobile phone number is registered on WhatsApp or not, check out the documentation on https://docs.wwebjs.dev/Client.html.
Note: you might need to sanitized the phone number first to ensure it is in the right format, which is , etc 618123456789.
61 is the country code, and the 08123456789 is the usual mobile number (remove the first zero on it).
var client = whatsAppWebClient.client;
var mobile_no = '628123456789';
// Get the registered WhatsApp ID for a number
var number_details = await client.getNumberId(sanitized_number);
if(number_details) {
console.log("Sending message to ", number_details);
/* send message */
} else {
console.log(sanitized_number, "Mobile no is not registered on
}
import {Client} from 'whatsapp-web.js';
const client = new Client({
// client configuration if any
})
// other blocks of code goes here
//function for checking if number is registered on whatsapp
const isNumberOnWhatsapp = async (number) => {
return await client.isRegisteredUser(number)
}
client.initialize()
Related
I am trying to make conference with Voximplant, and when user makes a call to another user, while the call is still going on, it makes another call to another user making two calls and the callees is added to a video conferencing.
But it seems the caller is billed twice and the scenerio doesnt look optimised. What should i do to bill once and optimize it?
Scenario:
require(Modules.Conference);
var call, conf = null;
VoxEngine.addEventListener(AppEvents.Started, handleConferenceStarted);
function handleConferenceStarted(e) {
// Create 2 conferences right after session to manage audio in the right way
if( conf === null ){
conf = VoxEngine.createConference(); // create conference
}
conf.addEventListener(CallEvents.Connected,function(){
Logger.write('Conference started')
})
}
VoxEngine.addEventListener(AppEvents.CallAlerting, function(e) {
e.call.addEventListener(CallEvents.Connected, handleCallConnected);
let new_call = VoxEngine.callUser(e.destination,e.callerid,e.displayName,{},true)
new_call.addEventListener(CallEvents.Connected,handleCallConnected);
e.call.answer();
});
function handleCallConnected(e) {
Logger.write('caller connected');
conf.add({
call: e.call,
mode: "FORWARD",
direction: "BOTH", scheme: e.scheme
});
}
You need to end the conference when there are no participants. Refer to the following article in our documentation: https://voximplant.com/docs/guides/conferences/howto. You can find the full scenario code there.
Additionally, I recommend to add some handlers for the CallEvents.Disconnected and the CallEvent.Failed events right after
new_call.addEventListener(CallEvents.Connected,handleCallConnected);
because sometimes the callee may be offline or press a reject button. 🙂
I am trying to use OpenSea API and I noticed that I need to set a limit before retrieving assets
https://docs.opensea.io/reference/getting-assets
I figured I can use the offset to navigate through all the items, even though that's tedious. But the problem is offset itself has a limit, so are assets beyond the max offset inaccessible ?
I read that you that the API is "rate-limited" without an API key, so I assume that related to the number of requests you can make in a certain time period, am I correct about that? Or does it lift the limit of returned assets ? The documentation isn't clear about that https://docs.opensea.io/reference/api-overview
What can I do to navigate through all the assets ?
May be late answering this one, but I had a similar problem. You can only access a limited number (50) assets if using the API.
Using the API referenced on the page you linked to, you could do a for loop to grab assets of a collection in a range. For example, using Python:
import requests
def get_asset(collection_address:str, asset_id:str) ->str:
url = "https://api.opensea.io/api/v1/assets?token_ids="+asset_id+"&asset_contract_address="+collection_address+"&order_direction=desc&offset=0&limit=20"
response = requests.request("GET", url)
asset_details = response.text
return asset_details
#using the Dogepound collection with address 0x73883743dd9894bd2d43e975465b50df8d3af3b2
collection_address = '0x73883743dd9894bd2d43e975465b50df8d3af3b2'
asset_ids = [i for i in range(10)]
assets = [get_asset(collection_address, str(i)) for i in asset_ids]
print(assets)
For me, I actually used Typescript because that's what opensea use for their SDK (https://github.com/ProjectOpenSea/opensea-js). It's a bit more versatile and allows you to automate making offers, purchases and sales on assets. Anyway here's how you can get all of those assets in Typescript (you may need a few more dependencies than those referenced below):
import * as Web3 from 'web3'
import { OpenSeaPort, Network } from 'opensea-js'
// This example provider won't let you make transactions, only read-only calls:
const provider = new Web3.providers.HttpProvider('https://mainnet.infura.io')
const seaport = new OpenSeaPort(provider, {
networkName: Network.Main
})
async function getAssets(seaport: OpenSeaPort, collectionAddress: string, tokenIDRange:number) {
let assets:Array<any> = []
for (let i=0; i<tokenIDRange; i++) {
try {
let results = await client.api.getAsset({'collectionAddress':collectionAddress, 'tokenId': i,})
assets = [...assets, results ]
} catch (err) {
console.log(err)
}
}
return Promise.all(assets)
}
(async () => {
const seaport = connectToOpenSea();
const assets = await getAssets(seaport, collectionAddress, 10);
//Do something with assets
})();
The final thing to be aware of is that their API is rate limited, like you said. So you can only make a certain number of calls to their API within a time frame before you get a pesky 429 error. So either find a way of bypassing rate limits or put a timer on your requests.
I am confused why me below snippet of code is showing null for email and fullName in console after user is authenticated successfully. I have read the documentation carefully and tried every possible thing I could. Any help would be highly appreciated.
async function onAppleButtonPress() {
// performs login request
const appleAuthRequestResponse = await appleAuth.performRequest({
requestedOperation: AppleAuthRequestOperation.LOGIN,
requestedScopes: [AppleAuthRequestScope.EMAIL, AppleAuthRequestScope.FULL_NAME],
});
//api getting current state of the user
const credentialState = await appleAuth.getCredentialStateForUser(appleAuthRequestResponse.user);
if (credentialState === AppleAuthCredentialState.AUTHORIZED) {
// user is authenticated
console.log("email is",appleAuthRequestResponse.email);
console.log("full name is",appleAuthRequestResponse.fullName);
}
}
You can still retrieve the e-mail from the identityToken provided by appleAuthrequestResponse with any jwt decoder like jwt-decode
const {identityToken, nonce, email} = appleAuthRequestResponse
const {email} = jwt_decode(identityToken)
console.log(email)
Apple only returns the full name and email on the first login, it will return null on the succeeding login so you need to save those data.
To receive these again, go to your device settings; Settings > Apple ID, iCloud, iTunes & App Store > Password & Security > Apps Using Your Apple ID, tap on your app and tap Stop Using Apple ID. You can now sign-in again and you'll receive the full name and `email.
Source here.
Current app is Expo for React Native which is ejected to the bare workflow.
Using expo-in-app-purchases for IAP.
How can you tell if a subscription is active or not?
When I grab the purchase history via:
const { results } = InAppPurchases.connectAsync();
if you look at the results, a result returns the following fields:
purchaseTime
transactionReceipt
orderId
productId
acknowledged
originalPurchaseTime
originalOrderId
purchaseState
Now purchaseState is always an integer. I'm mostly seeing 3 (I think I've seen a 1 one time...) Not sure this actually tells me anything valuable as they are all 3s
Short of manually taking the most recent purchase and adding 30 days (this is a monthly subscription) then seeing if this date is in the past, I'm not sure how to find if current user has active subscription. Help!
Thanks in advance!
Apple gives you the receipt as a signed and base64-encoded string. In order to see the contents of the receipt (including the 'expires at' date), you need to send this receipt to Apple's receipt verification endpoint along with your app-specific password.
More info here: https://developer.apple.com/documentation/storekit/in-app_purchase/validating_receipts_with_the_app_store
A function similar to this worked for me. This retrieves the receipt info as a JSON object and inside there is expires_at_ms, which can be compared to today's date to see if the subscription has expired.
async validateAppleReceipt(receipt) {
const prodURL = 'https://buy.itunes.apple.com/verifyReceipt'
const stagingURL = 'https://sandbox.itunes.apple.com/verifyReceipt'
const appSecret = '1234...'
const payload = {
"receipt-data": receipt,
"password": appSecret,
"exclude-old-transactions": true,
}
// First, try to validate against production
const prodRes = await axios.post(prodURL, payload)
// If status is 21007, fall back to sandbox
if (prodRes.data && prodRes.data.status === 21007) {
const sandboxRes = await axios.post(stagingURL, payload)
return sandboxRes.data.latest_receipt_info[0]
}
// Otherwise, return the prod data!
return prodRes.data.latest_receipt_info[0]
}
Have you tried to use
const { responseCode, results } = await getPurchaseHistoryAsync(true);
I am using this filter hook in my Auth0 Delegated Administration Extension.
function(ctx, callback) {
// Get the company from the current user's metadata.
var company = ctx.request.user.app_metadata && ctx.request.user.app_metadata.company;
if (!company || !company.length) {
return callback(new Error('The current user is not part of any company.'));
}
// The GREEN company can see all users.
if (company === 'GREEN') {
return callback();
}
// Return the lucene query.
return callback(null, 'app_metadata.company:"' + company + '"');
}
When user logged in whose company is GREEN can see all users. But when user logged in whose company is RED can't see any users whose company is RED.
I need to make this when user logged in, user should only be able to access users within his company. (except users from GREEN company).
But above code is not giving expected result. What could be the issue?
This might be related to a little warning note on the User Search documentation page
Basically they don't let you search for properties in the app_metadata field anymore. Unfortunately, this change was breaking and unannounced.
We had to make changes to our API so that we keep a copy of the app_metadatas in a separate database and convert lucene syntax to MongoDB queries, so that we can query by a chain of user_id:"<>" OR user_id:"<>" OR ....
One caveat though, you can't pass a query that's longer than 72 user_ids long. This number is so far undocumented and obtained empirically.
Also, you can't rely on Auth0's hooks to add new users to your database, as these don't fire for social logins, only for Username-Password-Authentication connections.
I hope this gave you some explanation as for why it wasn't working as well as a possible solution.
If I were you, I would look for an alternative for Auth0, which is what we are currently doing.
I finally ended up with this solution.
Used search functionality to filter users. I had to change below two files.
fetchUsers function in client\actions\user.js
changed
export function fetchUsers(search = '', reset = false, page = 0)
to
export function fetchUsers(search = '#red.com', reset = false,
page = 0)
AND
onReset function in client\containers\Users\Users.jsx
changed
onReset = () => { this.props.fetchUsers('', true); }
to
onReset = () => { this.props.fetchUsers('#red.com', true); }