Saturday, February 17, 2024

Automating WhatsApp - Part 2: On Windows Machines

 


In my previous post (Automating WhatsApp Using AppleScript), I created a simple script that allows a personal user to make delivering personalized messages using WhatsApp streamlined (still requiring some manual work, but very little...).

The problem with the previous solution was that it only works on Mac, and I know many of my friends are using Windows machines. Some asked me to adapt my solution to Windows, so I had to install Parallels on my Mac (a very smooth and nice experience - more on that later), and instal Visual Basic .Net (the free community edition), and re-learn my VisualBasic/.Net skills... 

The solution I came up with is not totally robust and has some drawbacks, but it might help someone, so here it is..

How To Use

1. Install the app: and Installer for the app is available here: https://bit.ly/3I2mSu7, the file is a zip file with a setup.exe installer. There is also a sample data files folder to help you get started.

2. Make Sure Microsoft Edge is your default browser, and log in to web.whatsapp.com on the browser before you run the tool. Close WhatsApp tabs, but leave the session open (have some other tab open).

Run the TellMyFriends app, select the data file (data.csv), which should live in a folder alongside the text templates (explained later). Once you select the file, a preview of your list is shown, and you can then click the start button when you want to send the messages.

3. For each recipient, the tool will open the browser with a whatsapp tab, and start a chat with the phone number, and the message for the user.

Example Files

1, Data.csv

name,phone,template

John,12123334444,friend.txt

Elena,12123335555,work.txt

Noa,12123336666,friend.txt


2. Templates (in the above file three templates are referenced, here is an example of one - work.txt):

Dear FNAME,
as a work colleague I would love to see you at my birthday party this Saturday 8pm
My address is 102 Main St. Someville
Hope to see you there!
Srool

Any occurence of the FNAME in the template will be replaced by the recipient name.

Behind The Scenes - For Developers

OK, the code is written in VB.Net (using the community edition of Visual Studio).

This is the form I designed:



And the code can be found in this GitHub repo:




Thursday, February 15, 2024

Automating WhatsApp Using AppleScript



Edit: added a windows version, and all source code is available here: https://github.com/iroth/TellMyFriends




I was looking for a way to send a message to a distribution list. This is a feature that in its simplest form is part of the WhatsApp mobile app, but its a bit cumbersome, and what's more - it does not allow to customize messages for each recipient.

There are third party tools, and WhatsApp business API, but I am just a simple guy who needs to send his friends some personal messages (think about invitations to a party or greetings for the holidays), so I was trying all kind of ways, and then found a reasonable solution using JavaScript in Mac Script Editor.

The idea is to create a data file with a list of recipients, at the minimum it is something like:

{
"recipients": [
{"name": "John", "phone": "12123334444"},
{"name": "Marry", "phone": "12123335555"},
{"name": "Anna", "phone": "12123336666"},
]
}

With a first name and phone number.

Save the list to a file named "data.json" in a new empty folder.

Create a message template file, like this:

Hello FNAME,
I would love to invite you to my birthday party on Saturday night at 8PM.
Lots of food and beer - don't eat too much before the party...
see ya!

Save this to a file called "template.txt" in that same folder as the data.json file.

Then create this script (since I use Hebrew, I needed to read the file as UTF-8):

ObjC.import('Foundation')


const readFileEnc = function (path, encoding) {

    !encoding && (encoding = $.NSUTF8StringEncoding)


    const fm = $.NSFileManager.defaultManager

    const data = fm.contentsAtPath(path)

    const str = $.NSString.alloc.initWithDataEncoding(data, encoding)

    return ObjC.unwrap(str)

}


const sendOneMessage = function (chromeapp, window, url) {


 var ic = window.tabs.length;

 window.tabs.push(new chrome.Tab());

  window.tabs[1].url = url;

  while (window.tabs.length > ic) {

  this.console.log("waiting...");

  }


}


var app = Application("Script Editor");

app.includeStandardAdditions = true;

var folder = app.chooseFolder({ withPrompt: 'Please select the data folder' })

var file = folder + "/data.json";

var dataStr = readFileEnc(file)

var data = JSON.parse(dataStr);


var chrome = Application('Google Chrome');

var window = chrome.Window().make();

var countDoc = 0;


for (var i = 0 ; i < data.recipients.length ; i++) {

var tfile = folder + "/template.txt";

var text = readFileEnc(tfile);

text = encodeURIComponent(text.replace(/FNAME/g, data.recipients[i].name));

var dest_url = "https://web.whatsapp.com/send/?phone=" + data.recipients[i].phone + "&text=" + text + "&type=phone_number";

sendOneMessage(chrome, window, dest_url);

countDoc++;

}


window.close();


countDoc


Before you run this script, make sure you logged in to WhatsApp Web in Chrome. The script will open a new window in Chrome, and then a tab with WhatsApp Web setup with the phone number and text ready for you, click the send button manually, and close the tab to get the next record opened. 

If you only have 30-40 recipients, this will be quite a smooth and fulfilling experience.

Enjoy!


Friday, August 13, 2021

NanoEuclid - An Arduino Based Euclidean Sequencer

 NanoEuclid

Arduino-based Euclid Rhythm Sequencer

Features

This sequencer is inspired by Euclidean Circles v2 by vpme.de.

It has 4 channels: A, B, C, D

Internal (with tempo control) or external clock operation

Each channel can adjust the pattern length (1-16) and number of active spots in the pattern (1 to pattern length) and the offset of the pattern start within the cycle

The euclidean “algorithm” places the active beats within the pattern of a given length in a way that spreads them equally as much as possible.




A 16 color led circle shows the parameters and a rotary encoder at the center of the ring is used as the main interactive control

The module provides 4 gate signals for Eurorack.

Each channel can have a different pattern, and the 4 channels together with their patterns constitute a “patch”.

Up to 16 patches can be saved and later loaded from EEPROM, so if you got something cool, it will not be lost..

The module has a play/stop button, and once playing can be triggered from an internal clock whose rate is controlled with a potentiometer, or switched to use an external clock from Eurorack.

User Interface

  1. int/ext toggle switch - setting the clock source

  2. Tempo pot. - used when clock is internal to set the tempo BPM

  3. 16 RGB Led circle (Nano Pixels) to show setup, pattern and real time playback

    1. Channel Colors are Yellow, Orange, Light Red and Red, where the leds in those color show the pattern length.

    2. According to the mode (selected by pushing the rotary encoder), the actrive beats are shown in Purple (edit number of active), Blue (edit pattern offset), Cyan (edit pattern length).

    3. When in play mode, the current step is highlighted in green

    4. In Store mode (entered by long clicking the rotaty encoder), the whole 16 pixels are turned red (if the corresponding slot is free) or green (if the corresponding memory slot is taken). Selected memory position is highlighted in white. Selected position is moved with the rotary encoder. Clicking the CHN/store button stores the current pattern to the selected position (overriding existing stored pattern if there was one). If the selected position is a programmed one (Green), clicking the PLAY/load button loades the stored patch to the active pattern.

  1. PLAY push button (toggles between start and stop modes)

  2. Rotary encoder with push button action to set parameters as described above

  3. CHN Select push button - cycles between the 4 channels



User Interface

The circuit is based on an Arduino Nano Every board, as shown below.

  1. Clock input - a 2N3904 transistor is used as an inverting buffer to protect the arduino, two resistors and a diode are connected (one resistor from input to base, one resistor from collector to +5V, diode cathode to base, anode to ground). Input from collector to D10.

  2. Gate outputs - digital pins 2,3,4,5 go to gate output

  3. NeoPixels ring - digital pin 6 drives the LED ring

  4. Rotary encoder inputs - D7, D8

  5. Rotary encoder switch - D9

  6. Play/Stop push connected as INPUT PULLUP to ground and D11

  7. Channel select push is connected to ground and to A3, A3 connected with 1M resistor to v+

  8. Int/Ext Switch - ground to D12


Storage

EEPROM size on Nano Every is 256 bytes, we would like to store patches into it, so they can be called upon later and survive power downs.

This section explains the arrangement of the data in this rather small memory space.

Each patch consists of 4 channels, each channel has 3 parameters: pattern length, number of active beats and offset. Each parameter can be stored in 4 bits, so the channel data is stored in 1.5 bytes, and the whole 4 channels in 8 bytes.

As the GUI consists of 16 LEDS, we will limit the pattern storage to 16 patches, to simplify the user interface.

To simplify managing the memory, we can store 2 bytes of 16 bits telling us if the respective slot is already stored.


offset

Byte 0

Byte 1

0

Magic Pattern ($AAAA)

2

Bitmap of taken slots for patches (1=taken)

4

PATCH #0

Pattern Length A

PATCH #0

Active Beats A

PATCH #0

UNUESDE Nibble (0x00)

PATCH #0

Offset A

6

PATCH #0

Pattern Length B

PATCH #0

Active Beats B

PATCH #0

UNUESDE Nibble (0x00)

PATCH #0

Offset B

8

PATCH #0

Pattern Length C

PATCH #0

Active Beats C

PATCH #0

UNUESDE Nibble (0x00)

PATCH #0

Offset C

10

PATCH #0

Pattern Length D

PATCH #0

Active Beats D

PATCH #0

UNUESDE Nibble (0x00)

PATCH #0

Offset D

12

PATCH #1

Pattern Length A

PATCH #1

Active Beats A

PATCH #1

UNUESDE Nibble (0x00)

PATCH #1

Offset A

14

PATCH #1

Pattern Length B

PATCH #1

Active Beats B

PATCH #1

UNUESDE Nibble (0x00)

PATCH #1

Offset B

16

PATCH #1

Pattern Length C

PATCH #1

Active Beats C

PATCH #1

UNUESDE Nibble (0x00)

PATCH #1

Offset C

118

PATCH #1

Pattern Length D

PATCH #1

Active Beats D

PATCH #1

UNUESDE Nibble (0x00)

PATCH #1

Offset D


Storage

The source code is available at this repo here:
https://github.com/iroth/nanoeuclid
See the readme for additional info, and feel free to comment, or branch...