http://qs321.pair.com?node_id=1216772

Welcome to Part 3 of How to write apps for macOS/OSX in Perl! This app protects Internet Privacy by regularly changing DNS servers. It's designed to run constantly in the background. I use it all day every day for the past 2 months.

This edition demonstrates how to:

  1. Write a very useful application!
  2. Use Perl to create, read and write a config file.
  3. Easily edit the config file.
  4. Configure multiple run time variables.
  5. Pass variables between Applescript and Perl.
  6. Handle errors and bad input.
  7. Use core Perl modules.

See Part 1 to get started with Perl and the built-in Mac devtool Automator,
and the demo Perl app for Mac: Perl ASN Check

See Part 2 for more techniques to integrate Perl into Mac with Applescript,
and the demo Perl app for Mac: Perl Version Tool

This ~150 liner is ~120 lines of Applescript GUI logic linked to ~30 lines of core Perl code in the form of 3 one-liners! Hopefully our Mac-centric monks will pick up these techniques to write and share Mac apps to improve computing experiences with Perl! Remember: All Macs Have Perl!

Source:

-- Set random DNS server every n minutes. # Demonstration Apple macOS/OSX app in AppleScript and Perl # Posted to perlmonks.org by Anonymous Monk 6/16/2018 # Node: How to write apps for macOS/OSX in Perl! Part 3: Random DNS Se +rver -- Part 1: Perl ASN Check https://perlmonks.org/?node_id=1216610 -- Part 2: Perl Version Tool https://perlmonks.org/?node_id=1216670 # DEFAULT DNS SERVERS: # 1.1.1.1 = Cloudflare # 8.8.8.8 = Google # 45.77.165.194 = Fourth Estate Zero Knowledge set DNS to "1.1.1.1 8.8.8.8 45.77.165.194" set DEFAULT_NETWORK to "Wi-Fi" set TITLE to "Random DNS Server" # CREATE AND/OR READ CONFIGURATION FILE: # 1. PASS APPLESCRIPT VARIABLES TO PERL -> # 2. SEND PERL VARIABLES TO APPLESCRIPT <- # 3. AND THAT LAST LINE... try set INI to do shell script "printf $HOME" & "/.dns.random.config" set CFG to do shell script " perl -Mautodie -we ' my $config = qq~" & INI & "~; if (-e $config) { open my $fh, q~<~, $config; @_ = <$fh>; close $fh; @_ = grep /\\S+/, @_; print @_; } else { open my $fh, q~>~, $config; print $fh qq~" & DNS & "~; close $fh; print qq~" & DNS & "~; } ' " on error oops display alert oops as critical end try set DNS to CFG # RUNTIME CONFIG LOOP repeat try set TXT to "DNS Servers: " & DNS & " Minutes between change? (blank to exit)" set EAE to "EXIT AND EDIT CONFIG" # GET DIALOG OBJECT CONTAINING INPUT AND CLICKED BUTTON VALUE set DUR to display dialog TXT with title TITLE default answer +"" buttons {EAE, "OK"} default button 2 set DUR_text to text returned of DUR as number set DUR_button to button returned of DUR if DUR_button is EAE then # EDIT CONFIG try do shell script "open -a TextEdit " & INI & "" return # EXIT on error oops display alert oops as critical return # EXIT end try end if if DUR_text is 0 then return # EXIT set DUR to DUR_text set NETS to do shell script "networksetup -listallnetworkservi +ces" set TXT to "Network Interfaces: " & NETS & " Network?" set NETWORK to text returned of (display dialog TXT with title + TITLE default answer DEFAULT_NETWORK buttons {"OK"} default button 1 +) try # DOES NETWORK EXIST? set hmm to do shell script " perl -we ' @_ = qx/networksetup -getinfo " & NETWORK & "/; $_ = join qq~\\n~, @_; print /Error/ ? 0 : 1; ' " on error oops display alert oops as critical return # EXIT end try if hmm as number is equal to 0 then display notification "Network not found! Exit..." with tit +le TITLE return # EXIT end if exit repeat # EXIT CONFIG LOOP on error oops display notification "This shouldn't happen!" with title TITLE return # EXIT end try end repeat # END CONFIG LOOP set MSG to button returned of (display dialog "Notification of change? +" buttons {"No", "Yes"} default button 2) # END CONFIG # MAIN EVENT LOOP repeat try # Use perl to read last line of resolv.conf as current DNS ser +ver. # Exclude current server and shuffle list to get new value. # Set new server and return the old and new values to applescr +ipt. set PERL to do shell script " perl -MList::Util=shuffle -Mautodie -we ' open my $fh, q~<~, q~/private/etc/resolv.conf~; chomp(@_ = <$fh>); close $fh; $_ = pop @_; my (undef,$cur) = split q~ ~; $_ = qq~" & DNS & "~; @_ = split /\\s+/; @_ = grep !/$cur/, @_; @_ = shuffle @_; my $new = pop @_; system(qq~networksetup -setdnsservers " & NETWORK & " +$new~); print qq~$cur $new~; ' " on error oops display alert oops as critical end try # AN APPLESCRIPT SPLIT set text item delimiters to {" "} set {CUR, NEW} to text items 1 thru 2 of PERL if MSG is "Yes" then display notification "DNS changed from " & CUR & " to " & NEW +with title TITLE end if delay ((DUR as integer) * 60) end repeat # MADE IN USA (This program, Perl, Apple, Me!) # b9ce5dcd671f9647fb86a6f3709a572ffd6e2aa490c005300585a555fabf9ce8 # 060c38ad8715a6a2381cc653ad5a7dd1815f3cf990c31594b4a1b20ef4fc9d27