2024-11-04 02:30:00
The recent release of Apple Intelligence has added a new set of helpful AI writing tools to your Mac. You can proofread emails, summarize documents and, the most useful of all, rewrite emails in professional or casual tone. You can access the writing tools wherever you type text on your Mac - in the Mail app, Gmail, Safari browser, and any other text editor.
Apple Intelligence is available on Macs running macOS Sequoia 15.1 and the device language is set to US English. The built-in AI integration means you can enhance your writing directly in your current app, without jumping back and forth between ChatGPT or Copilot in a separate window.
To access the AI writing tools inside your current app, you can select the text you want to edit, right-click and select Writing Tools
> Show Writing Tools
from the context menu.
If you prefer to use a keyboard shortcut to launch the writing tools on your Mac, here’s how you can do it.
Settings
app on your Mac and select Keyboard
. Click the Keyboard Shortcuts
button.App Shortcuts
section and click the +
button to create a new shortcut.Menu Title
field, enter Show Writing Tools
while the Application field is set to All applications. In the Keyboard Shortcut
field, press Command Shift .
(period key). Click Add
.That’s it. Restart your current app and select the text you want to edit. Press Command Shift .
to launch the writing tools without touching the mouse.
2024-10-07 02:30:00
You are running a small software business that sells digital downloads - apps, plugins, or even templates. When the buyer completes the purchase, you need to provide them with a license key that they can use to activate and validate the software.
Here’s how you can implement such a licensing system in your software:
The advantage here is that the public key can be included in the software’s source code, there’s no need to use a database, and the buyer can verify the license key offline without the need to connect to your server.
Let’s now go through the implementation steps in detail.
We’ll generate a public and private key pair using the RSA algorithm. Launch the terminal and run the following openssl command.
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out private_key.pem
It will generate a 2048-bit RSA private key and save it to a file called private_key.pem
in the current folder. Next, we’ll write a command to generate a public key from the private key.
openssl rsa -pubout -in private_key.pem -out public_key.pem
Now that we have our keys, let’s print them to the console as we’ll need them in the next step.
openssl pkey -in private_key.pem && openssl pkey -pubin -in public_key.pem
We’ll write a simple Node.js script to generate a license key. It uses the crypto
module to sign the message with the private key and the fs
module to read the private key from the file system.
const crypto = require('crypto');
const fs = require('fs');
// Read private key from file system
const privateKey = fs.readFileSync('private_key.pem', 'utf8');
const buyerEmailAddress = '[email protected]';
const data = Buffer.from(buyerEmailAddress);
const signature = crypto.sign('sha256', data, {
key: privateKey,
padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
});
// Convert the signature to base64
const licenseKey = signature.toString('base64');
// Output the result
console.log(licenseKey);
The license key generated in the previous step is sent to the buyer’s email address and we need to verify it when the buyer activates the software.
This again is a simple Node.js script that uses the crypto
module to verify the license key with the public key.
const crypto = require('crypto');
const fs = require('fs');
const buyerEmailAddress = '<<buyer email address>>';
const licenseKey = '<<license key>>';
const publicKey = fs.readFileSync('public_key.pem', 'utf8');
const signatureBuffer = Buffer.from(licenseKey, 'base64');
const licenseStatus = crypto.verify(
'sha256',
Buffer.from(buyerEmailAddress),
{
key: Buffer.from(publicKey),
padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
},
signatureBuffer
);
console.log(licenseStatus ? 'Activated' : 'Invalid license key');
If you are planning to include activation inside Google Workspace add-ons, you can build a Google Cloud Function or a Google Cloud Run service to handle the license activation.
Your Apps Script code can make a UrlFetch POST request to the web service with the license key and get back the activation status. In such a case, the public key need not be embedded in the script. Also, the user’s email address can be easily retrieved using the Session.getActiveUser().getEmail()
method.
This is obviously a basic implementation of a software licensing system that doesn’t handle all the edge cases. It can be a starting point but there are many other things to consider like:
2024-10-05 02:30:00
Zoho Payments is a new payment gateway that lets you accept payments on your website. You can visit this sample store to see the Zoho Payments widget in action.
Unlike Stripe or RazorPay which are more mature payment gateways, Zoho Payments only supports domestic payments in INR (₹). In the initial release, merchants can only accept one-time payments and customers can pay you with UPI, Net Banking, and Credit Cards.
The onboarding process is simple and, once you have uploaded your KYC documents, your account is approved within few business days. There’s no transaction fee for UPI payments while credit card transactions are subject to a 2% fee (excluding GST)
In this tutorial, we’ll create a simple payment page in Google Apps Script and accept payments on our website using Zoho Payments.
Assuming that you have signed up for Zoho Payments, you can visit the dashboard to find your “Account ID”. Next, go to Settings > Developer Space to find your “API Key”.
Open the Google Script project and make a copy in your Google Drive.
Inside the Apps Script editor, go to function dropown and select printZohoPaymentsRedirectUrl
. Run the script and you should see a URL in the console window.
Go to your Zoho API Console api-console.zoho.in and add a new client. Set the Client Type
to Server-based Applications
and paste the Redirect URL from the previuos step in the Authorized Redirect URLs
field. Give your application a name like MyPaymentsApp
and click on Create
. Make a note of the Client ID
and Client Secret
as we’ll need them in the next step.
Go back to the Apps Script editor and paste the Client ID
and Client Secret
in the corresponding variables. You will also need to paste your Account ID
and API Key
in the code.
Next, run the printZohoPaymentsAuthUrl
function to generate the authorization URL. Open the URL in a new tab, allow the app to access your Zoho Payments data and you should see a success message. We are limiting the scope of the application to ZohoPay.payments.CREATE
so that our application can only create payments but not read or update any other data.
Once the application is authorized, click the Deploy
button and select New Deployment
. Select the type as Web app
, set the Execute as
to Me
and Who has access
to Anyone.
Click on Deploy
and you will get the URL of your web payments page. Anyone can now make a payment by visiting this URL.
The app uses the OAuth2 library to handle the authorization process and generate the access token for connecting to the Zoho Payments API.
const getZohoPaymentsService_ = () => {
return OAuth2.createService(ZOHO_SERVICE_NAME)
.setAuthorizationBaseUrl('https://accounts.zoho.in/oauth/v2/auth')
.setTokenUrl('https://accounts.zoho.in/oauth/v2/token')
.setClientId(ZOHO_PAYMENTS_CLIENT_ID)
.setClientSecret(ZOHO_PAYMENTS_CLIENT_SECRET)
.setCallbackFunction('zohoOauthCallback')
.setPropertyStore(PropertiesService.getScriptProperties())
.setCache(CacheService.getScriptCache())
.setParam('response_type', 'code')
.setScope('ZohoPay.payments.CREATE')
.setParam('access_type', 'offline')
.setParam('prompt', 'consent');
};
The createZohoPaymentSession
function is used to create a new payment session. It takes the amount as a parameter and returns the payment session details which are then passed to the Zoho Payments widget on the client side.
const createZohoPaymentSession = (amount) => {
const service = getZohoPaymentsService_();
const baseUrl = 'https://payments.zoho.in/api/v1';
const apiUrl = `${baseUrl}/paymentsessions?account_id=${ZOHO_PAYMENTS_ACCOUNT_ID}`;
const response = UrlFetchApp.fetch(apiUrl, {
method: 'post',
payload: JSON.stringify({ amount, currency: 'INR' }),
headers: {
Authorization: `Zoho-oauthtoken ${service.getAccessToken()}`,
'Content-Type': 'application/json',
},
muteHttpExceptions: true,
});
const result = JSON.parse(response.getContentText());
const { message, payments_session } = result;
return message === 'success'
? {
account_id: ZOHO_PAYMENTS_ACCOUNT_ID,
api_key: ZOHO_ACCOUNT_API_KEY,
merchant_name: ZOHO_MERCHANT_NAME,
session_id: payments_session.payments_session_id,
order_amount: payments_session.amount,
}
: { error: message };
};
You can find the complete code on GitHub.
2024-10-03 02:30:00
If you are running an online store running on WordPress, chances are you are using WooCommerce to manage your customers and orders. The holiday season in near and you may want to send your existing customers a special discount code for their next purchase. Or you may want to analyze your store’s data to see how your business is performing in various regions.
You can the built-in export feature of WooCommerce to export your customers data to a CSV file and then import the CSV file into Google Sheets. Go to your WooCommerce dashboard, navigate to the Customers section, and you’ll find an option to download the customers list as a CSV file.
If you are however looking for a more efficient way to export your WooCommerce customers to Google Sheets, you can use Google Apps Script to create a custom script that will export the customers to a Google Sheet.
To get started, you’ll create an API key in WooCommerce. Go to your WooCommerce dashboard, navigate to the Settings section, and then click on the “Advanced” tab. Go to the “Rest API” section and click on the “Create API Key” button.
On the next screen, you’ll be asked to enter a name for the API key. You can use a name like “Import Customers to Google Sheets” or something similar. You can restrict the API key permissions to read only, which is all we need since we’re only going to be reading customer data and not modifying any data.
WooCommerce will generate the consumer key and consumer secret for you. You’ll need to save the secret key somewhere, as you won’t be able to access it later from the WooCommerce dashboard.
Now that you have your WooCommerce credentials, let’s create a Google Sheet to store the customer data. Type sheets.new
in your browser’s address bar to create a new spreadsheet. Go to Extensions > Apps Script to open the Google Apps Script editor associated with your spreadsheet.
Paste the following code into the Apps Script editor. Remember to replace the WooCommerce consumer key, consumer secret and WordPress domain with your own values. Do not add a slash at the end of the WordPress domain.
const MAX_PER_PAGE = 100;
const CONSUMER_KEY = '<<YOUR_CONSUMER_KEY>>';
const CONSUMER_SECRET = '<<YOUR_CONSUMER_SECRET>>';
const WORDPRESS_DOMAIN = '<<YOUR_WORDPRESS_DOMAIN>>';
const fetchWooCommerceCustomers = () => {
const bearerToken = Utilities.base64Encode(`${CONSUMER_KEY}:${CONSUMER_SECRET}`);
const getQueryString = (options) => {
return Object.keys(options)
.map((key) => `${key}=${options[key]}`)
.join('&');
};
const getApiUrl = (pageNum) => {
const options = {
context: 'view',
page: pageNum,
per_page: MAX_PER_PAGE,
order: 'desc',
orderby: 'id',
role: 'customer',
};
return `${WORDPRESS_DOMAIN}/wp-json/wc/v3/customers?${getQueryString(options)}`;
};
// Fetches a single page of customer data.
const fetchPage = (pageNum) => {
const url = getApiUrl(pageNum);
const response = UrlFetchApp.fetch(url, {
headers: {
'Content-Type': 'application/json',
Authorization: `Basic ${bearerToken}`,
},
});
return JSON.parse(response.getContentText());
};
let page = 1;
let allCustomers = [];
let hasMore = true;
do {
const customers = fetchPage(page);
allCustomers = allCustomers.concat(customers);
page += 1;
hasMore = customers.length === MAX_PER_PAGE;
} while (hasMore === true);
return allCustomers;
};
The above script will fetch all the customers from your WooCommerce store. Next, we’ll add a function to flatten the customer data and store it in a Google Sheet.
To flatten the customer data, we’ll add the following function to the script.
const parseCustomer = (customer) => {
const { id, first_name, last_name, email, billing = {} } = customer;
return {
customer_id: id,
first_name,
last_name,
customer_email: email,
billing_first_name: billing.first_name,
billing_last_name: billing.last_name,
billing_email: billing.email,
billing_phone: billing.phone,
billing_address_1: billing.address_1,
billing_address_2: billing.address_2,
billing_city: billing.city,
billing_state: billing.state,
billing_postcode: billing.postcode,
billing_country: billing.country,
};
};
To store the customer data in a Google Sheet, we’ll add the following function to the script.
const exportCustomersToGoogleSheet = () => {
const wooData = fetchWooCommerceCustomers();
const customers = wooData.map(parseCustomer);
const headers = Object.keys(customers[0]);
const rows = customers.map((c) => headers.map((header) => c[header] || ''));
const data = [headers, ...rows];
const sheet = SpreadsheetApp.getActiveSpreadsheet().insertSheet();
sheet.getRange(1, 1, data.length, data[0].length).setValues(data);
const message = rows.length + ' customers exported to sheet ' + sheet.getName();
SpreadsheetApp.getUi().alert(message);
};
Inside the Apps Script editor, click on the “exportCustomersToGoogleSheet” function and then click on the “Run” button. Authorize the script and watch as your customers data from WooCommerce magically appears in your Google Sheet.
You can then use Gmail Mail Merge to send personalized emails to your customers right inside the Google Sheet.
2024-09-04 02:30:00
Let’s say you have a Github repository where you push all your code changes. Each commit has a unique commit hash, and you can use this hash to restore the code to a specific commit or a particular time.
It is advisable that you take a backup of your current code before proceeding.
To get started, open your repository on Github and find the commit you want to restore. You can do this by clicking on the “Commits” tab and finding the commit in the list. If you want to restore to a particular date, you can use the calendar dropdown to see all the commits for that day and find the one you want.
You may also use the command line to find the commit hash.
git log --oneline
Once you have found the commit you want to restore, you can create a new branch at that commit. Let’s call this branch working-branch
.
git checkout -b working-branch <commit-hash>
This git
command will create a new branch named working-branch
pointing to the specified commit and switches to that branch.
Next, you can force push the new branch to the remote repository.
git push -f origin working-branch
Now that you have a new branch with the code at the specific commit, you can update the main branch to this restored state.
git checkout main
git reset --hard working-branch
git push -f origin main
⚠️ Please be careful when using these git
commands since it will permanently delete all code changes made after the commit you are restoring.