0

I'd like to be able to remove a batch of people from a "private" Slack channel.

Use case: whoops, I just added 137 people to the wrong channel!

The Slack Member ID list is obtained from an Airtable spreadsheet column.

  1. copy the range of cells from Airtable
  2. format the values into a single-space separated string
  3. prepend the Channel ID to the MemberID list

Structure the input arguments like so:

$ sh script.sh ChannelID MemberID1[ MemberID2 MemberID3 ...]

#!/bin/bash
args=("$@")
channel=${args[0]}
for arg in "${@:2}"; do
  curl -X POST \
    -H 'Authorization: Bearer foobar' \
    -H "Content-Type":"application/json; charset=utf-8" \
    --data '{"channel":"'"$channel"'", "user":"'"$arg"'"}' \
    https://slack.com/api/conversations.kick;
done

The Slack API method I am cURLing is limited to acting upon one MemberID at a time, and limited to only accepting 50 cURL POSTs per minute (Tier 3). I'd like to take a 50+ list of MemberIDs, and make sure they only get cURL'd in 50-member batches that are a minute apart.

I started looking into xargs and made it as far as:

if [ ${#args[@]} -gt 2 ]; then
  echo "channel ID: $channel"
  echo "${#args[@]} items in the argument array"
  echo "${@:2}"
  xargs -n 2 <<<${@:2} | xargs -I {} echo {} | sed -e 's/ /,/g'
fi
$ sh test.sh FO1O2B3A4R 1 2 3 4 5 6 7 8 9 10 11
    channel ID: FO1O2B3A4R
    12 items in the argument array
    1 2 3 4 5 6 7 8 9 10 11
    1,2
    3,4
    5,6
    7,8
    9,10
    11

Can I use xargs to make the 50 member batch, then for each one of those members, fire off the cURL command, then wait one minute (sleep 60s) in between firing off the batches?

  • 2
    It would be just as fast, and easier to script, if you just did one at a time, and had a sleep 1.25 between each iteration. 50 per minute is a simple one per 1.2 seconds; with 0.05 seconds added for some wiggle room if the API has an interesting sense of time. – DopeGhoti Mar 19 at 16:10
  • Thanks @DopeGhoti - just add a sleep command after the curl command? Brilliant – Mr. Kennedy Mar 19 at 16:36
1

If you want to do stuff in batches of 50 then xargs -n 50 may be the way to go, with a while loop

eg

list="user1 user2 user3 user4 user5 user6 user7 user8 user9 user10 user11 user12 user13 user14 user15 user16 user17 user18 user19 user20 user21 user22 user23 user24 user25 user26 user27 user28 user29 user30 user31 user32 user33 user34 user35 user36 user37 user38 user39 user40 user41 user42 user43 user44 user45 user46 user47 user48 user49 user50 user51 user52 user53 user54 user55 user56 user57 user58 user59 user60 user61 user62 user63 user64 user65 user66 user67 user68 user69 user70 user71 user72 user73 user74 user75 user76 user77 user78 user79 user80 user81 user82 user83 user84 user85 user86 user87 user88 user89 user90 user91 user92 user93 user94 user95 user96 user97 user98 user99 user100"

echo "$list" | xargs -n 50 echo | while read line
do
  echo Do Something with $line
  sleep 61
done

If we run this we can see that the loop is run twice:

Do Something with user1 user2 user3 user4 user5 user6 user7 user8 user9 user10 user11 user12 user13 user14 user15 user16 user17 user18 user19 user20 user21 user22 user23 user24 user25 user26 user27 user28 user29 user30 user31 user32 user33 user34 user35 user36 user37 user38 user39 user40 user41 user42 user43 user44 user45 user46 user47 user48 user49 user50
Do Something with user51 user52 user53 user54 user55 user56 user57 user58 user59 user60 user61 user62 user63 user64 user65 user66 user67 user68 user69 user70 user71 user72 user73 user74 user75 user76 user77 user78 user79 user80 user81 user82 user83 user84 user85 user86 user87 user88 user89 user90 user91 user92 user93 user94 user95 user96 user97 user98 user99 user100

You can do anything you like inside the while loop

1

Since you already have the list in $@, an alternative would be to loop over it and sleep at the 50-batch marks:

#!/bin/bash
channel=$1
shift

index=0
while [ "$#" -gt 0 ]
do
  (( ++index ))
  curl # ... --data ... "user":"'"$1"'"
  (( index % 50 == 0 )) && sleep 60
  shift
done

I've elided most of the curl command to make it easier to see the structure of what I'm proposing. The first change is to pull off the channel name into its own variable, and shift that argument away. Then, the remaining elements of $@ are the usernames.

The next part is a simple while loop that runs as long as there are elements left in $@. Each time through the loop, we:

  • increment a counter
  • call curl on $1
  • sleep if we should
  • shift off the first element of $@
  • shift!!! that is amazing - thank you! – Mr. Kennedy Mar 19 at 22:27
  • 1
    The $1 will iterate through each user from the passed in arguments, yes. $# is the number of elements currently in $@ – Jeff Schaller Mar 19 at 22:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.