From 4688d523e8867e7527cdaf859c9cf71bae739a5c Mon Sep 17 00:00:00 2001 From: Lewis Lancaster Date: Thu, 26 Nov 2015 17:13:35 +0000 Subject: [PATCH 01/63] Ported fucking_coffee to PHP. I'm not porting anymore. --- php/Lib/Telnet.php | 264 +++++++++++++++++++++++++++++++++++++++++ php/fucking_coffee.php | 170 ++++++++++++++++++++++++++ 2 files changed, 434 insertions(+) create mode 100644 php/Lib/Telnet.php create mode 100644 php/fucking_coffee.php diff --git a/php/Lib/Telnet.php b/php/Lib/Telnet.php new file mode 100644 index 00000000..3409dc3a --- /dev/null +++ b/php/Lib/Telnet.php @@ -0,0 +1,264 @@ + + * Based on the code originally written by Marc Ennaji and extended by + * Matthias Blaser + * + * Extended by Christian Hammers + * Modified by Frederik Sauer + * + */ + +class Telnet { + + private $host; + private $port; + private $timeout; + private $stream_timeout_sec; + private $stream_timeout_usec; + + private $socket = NULL; + private $buffer = NULL; + private $prompt; + private $errno; + private $errstr; + private $strip_prompt = TRUE; + + private $NULL; + private $DC1; + private $WILL; + private $WONT; + private $DO; + private $DONT; + private $IAC; + + private $global_buffer = ''; + + const TELNET_ERROR = FALSE; + const TELNET_OK = TRUE; + + public function __construct($host = '127.0.0.1', $port = '23', $timeout = 10, $prompt = '$', $stream_timeout = 1) { + $this->host = $host; + $this->port = $port; + $this->timeout = $timeout; + $this->setPrompt($prompt); + $this->setStreamTimeout($stream_timeout); + + // set some telnet special characters + $this->NULL = chr(0); + $this->DC1 = chr(17); + $this->WILL = chr(251); + $this->WONT = chr(252); + $this->DO = chr(253); + $this->DONT = chr(254); + $this->IAC = chr(255); + + $this->connect(); + } + + public function __destruct() { + // clean up resources + $this->disconnect(); + $this->buffer = NULL; + $this->global_buffer = NULL; + } + + public function connect() { + // check if we need to convert host to IP + if (!preg_match('/([0-9]{1,3}\\.){3,3}[0-9]{1,3}/', $this->host)) { + $ip = gethostbyname($this->host); + + if ($this->host == $ip) { + throw new Exception("Cannot resolve $this->host"); + } else { + $this->host = $ip; + } + } + + // attempt connection - suppress warnings + $this->socket = @fsockopen($this->host, $this->port, $this->errno, $this->errstr, $this->timeout); + + if (!$this->socket) { + throw new Exception("Cannot connect to $this->host on port $this->port"); + } + + if (!empty($this->prompt)) { + $this->waitPrompt(); + } + + return self::TELNET_OK; + } + + public function disconnect() { + if ($this->socket) { + if (! fclose($this->socket)) { + throw new Exception("Error while closing telnet socket"); + } + $this->socket = NULL; + } + return self::TELNET_OK; + } + + public function exec($command, $add_newline = TRUE) { + $this->write($command, $add_newline); + $this->waitPrompt(); + return $this->getBuffer(); + } + + public function login($username, $password) { + try { + $this->setPrompt('login:'); + $this->waitPrompt(); + $this->write($username); + $this->setPrompt('Password:'); + $this->waitPrompt(); + $this->write($password); + $this->setPrompt(); + $this->waitPrompt(); + } catch (Exception $e) { + throw new Exception("Login failed."); + } + + return self::TELNET_OK; + } + + public function setPrompt($str = '$') { + return $this->setRegexPrompt(preg_quote($str, '/')); + } + + public function setRegexPrompt($str = '\$') { + $this->prompt = $str; + return self::TELNET_OK; + } + + public function setStreamTimeout($timeout) { + $this->stream_timeout_usec = (int)(fmod($timeout, 1) * 1000000); + $this->stream_timeout_sec = (int)$timeout; + } + + public function stripPromptFromBuffer($strip) { + $this->strip_prompt = $strip; + } // function stripPromptFromBuffer + + protected function getc() { + stream_set_timeout($this->socket, $this->stream_timeout_sec, $this->stream_timeout_usec); + $c = fgetc($this->socket); + $this->global_buffer .= $c; + return $c; + } + + public function clearBuffer() { + $this->buffer = ''; + } + + public function readTo($prompt) { + if (!$this->socket) { + throw new Exception("Telnet connection closed"); + } + + // clear the buffer + $this->clearBuffer(); + + $until_t = time() + $this->timeout; + do { + // time's up (loop can be exited at end or through continue!) + if (time() > $until_t) { + throw new Exception("Couldn't find the requested : '$prompt' within {$this->timeout} seconds"); + } + + $c = $this->getc(); + + if ($c === FALSE) { + if (empty($prompt)) { + return self::TELNET_OK; + } + throw new Exception("Couldn't find the requested : '" . $prompt . "', it was not in the data returned from server: " . $this->buffer); + } + + // Interpreted As Command + if ($c == $this->IAC) { + if ($this->negotiateTelnetOptions()) { + continue; + } + } + + // append current char to global buffer + $this->buffer .= $c; + + // we've encountered the prompt. Break out of the loop + if (!empty($prompt) && preg_match("/{$prompt}$/", $this->buffer)) { + return self::TELNET_OK; + } + + } while ($c != $this->NULL || $c != $this->DC1); + } + + public function write($buffer, $add_newline = TRUE) { + if (!$this->socket) { + throw new Exception("Telnet connection closed"); + } + + // clear buffer from last command + $this->clearBuffer(); + + if ($add_newline == TRUE) { + $buffer .= "\n"; + } + + $this->global_buffer .= $buffer; + if (!fwrite($this->socket, $buffer) < 0) { + throw new Exception("Error writing to socket"); + } + + return self::TELNET_OK; + } + + protected function getBuffer() { + // Remove all carriage returns from line breaks + $buf = preg_replace('/\r\n|\r/', "\n", $this->buffer); + // Cut last line from buffer (almost always prompt) + if ($this->strip_prompt) { + $buf = explode("\n", $buf); + unset($buf[count($buf) - 1]); + $buf = implode("\n", $buf); + } + return trim($buf); + } + + public function getGlobalBuffer() { + return $this->global_buffer; + } + + protected function negotiateTelnetOptions() { + $c = $this->getc(); + + if ($c != $this->IAC) { + if (($c == $this->DO) || ($c == $this->DONT)) { + $opt = $this->getc(); + fwrite($this->socket, $this->IAC . $this->WONT . $opt); + } else if (($c == $this->WILL) || ($c == $this->WONT)) { + $opt = $this->getc(); + fwrite($this->socket, $this->IAC . $this->DONT . $opt); + } else { + throw new Exception('Error: unknown control character ' . ord($c)); + } + } else { + throw new Exception('Error: Something Wicked Happened'); + } + + return self::TELNET_OK; + } + + protected function waitPrompt() { + return $this->readTo($this->prompt); + } +} \ No newline at end of file diff --git a/php/fucking_coffee.php b/php/fucking_coffee.php new file mode 100644 index 00000000..5ab70c78 --- /dev/null +++ b/php/fucking_coffee.php @@ -0,0 +1,170 @@ +IsWeekend( date('m.d.y') ) == false ) + { + + return false; + } + + /** + * Create a new telnet class + */ + + $this->telnet = new Telnet( $this->host, $this->port ); + + /** + * Once we have completed this, we can brew our coffee! + */ + + $this->BrewCoffee( function(){ + + /** + * Echo out a message + */ + + echo "coffee has been poured"; + + /** + * Unset + */ + + unset( $this->telnet ); + }); + + /** + * Return tue + */ + + return true; + } + + /** + * Brews our coffee + * + * @param $callback + */ + + public function BrewCoffee( $callback ) + { + + if( $this->telnet != null ) + { + + /** + * Execute and enter the password + */ + + $this->telnet->exec('Password: ' . $this->password); + + /** + * Brew the coffee + */ + + $this->telnet->exec('sys brew'); + + /** + * Wait + */ + + sleep( $this->delay ); + + /** + * Pour the coffee + */ + + $this->telnet->exec('sys pour'); + + /** + * Execute our callback + */ + + call_user_func( $callback ); + } + } + + /** + * Is this currently the weekend? + * + * @param $date + * + * @return bool + */ + + public function IsWeekend( $date ) + { + + if( date('N', strtotime( $date ) ) >= 6 ) + { + + return true; + } + + return false; + } + +} \ No newline at end of file From 44d5c574c8cb6530f151233d3cceb1bd3df12221 Mon Sep 17 00:00:00 2001 From: Cheng Huang Date: Thu, 26 Nov 2015 14:45:03 -0500 Subject: [PATCH 02/63] Add powershell script smack_my_bitch_up.ps1 --- powershell/smack_my_bitch_up.ps1 | 39 ++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 powershell/smack_my_bitch_up.ps1 diff --git a/powershell/smack_my_bitch_up.ps1 b/powershell/smack_my_bitch_up.ps1 new file mode 100644 index 00000000..46c3d8f4 --- /dev/null +++ b/powershell/smack_my_bitch_up.ps1 @@ -0,0 +1,39 @@ +$DAYOFWEEK = (Get-Date).DayOfWeek.value__; + +# Skip on weekends +if ($DAYOFWEEK -eq 6 -or $DAYOFWEEK -eq 7) { + return +} + +# Exit early if no sessions with my username are found +if ((QWINSTA $env:USERNAME | measure).Count -gt 0){ + return +} + +# Phone numbers +$MY_NUMBER='+xxx' +$HER_NUMBER='+xxx' + +$TWILIO_ACCOUNT_SID = 'xxx' +$TWILIO_AUTH_TOKEN = 'xxx' + +$REASONS= + 'Working hard', + 'Gotta ship this feature', + 'Someone fucked the system again' + +$RAND = Get-Random -Maximum $REASONS.Count + +$MSG="Late at work. $REASONS[$RAND]" + + +$BASE64AUTHINFO = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $TWILIO_ACCOUNT_SID,$TWILIO_AUTH_TOKEN))) + +#Send a text messag and Log errors +try{ + Invoke-RestMethod -Method Post -Headers @{Authorization=("Basic {0}" -f $BASE64AUTHINFO)} "https://api.twilio.com/2010-04-01/Accounts/$TWILIO_ACCOUNT_SID/Messages" -Body "From=$MY_NUMBER&To=$HER_NUMBER&Body=$MSG" > $null +} +catch{ + Write-Host "Failed to send SMS: $_" +} + From e6bb45fb96279a5e9a83761ddbe60bf7e05ea4fc Mon Sep 17 00:00:00 2001 From: Maxime Orefice Date: Fri, 27 Nov 2015 00:19:46 +0100 Subject: [PATCH 03/63] Update README.md Fix gem to use twilio API --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 12d4b995..623762d3 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ GMAIL_PASSWORD=password ``` For Ruby scripts you need to install gems: -`gem install dotenv twilio gmail` +`gem install dotenv twilio-ruby gmail` ## Cron jobs From b9c6dad2c5d015de100e43f90f616d1f5d6108a7 Mon Sep 17 00:00:00 2001 From: Julio Ordonez Viales Date: Thu, 26 Nov 2015 19:26:15 -0600 Subject: [PATCH 04/63] Update cron job to be executed on weekdays only Updated the cron job so that it only executes the scripts on weekdays, that way there is not need to check for this condition inside the scripts, updated the scripts as well --- README.md | 12 ++++++------ fucking_coffee.rb | 3 --- hangover.rb | 3 --- hangover.sh | 7 ------- python/fucking_coffee.py | 7 ------- python/hangover.py | 7 ------- python/smack_my_bitch_up.py | 8 -------- python3/fucking_coffee.py | 5 ----- python3/hangover.py | 5 ----- python3/smack_my_bitch_up.py | 5 ----- smack-my-bitch-up.sh | 7 ------- smack_my_bitch_up.rb | 3 --- 12 files changed, 6 insertions(+), 66 deletions(-) diff --git a/README.md b/README.md index 12d4b995..67ee79e8 100644 --- a/README.md +++ b/README.md @@ -42,17 +42,17 @@ For Ruby scripts you need to install gems: ## Cron jobs ```sh -# Runs `smack-my-bitch-up.sh` daily at 9:20 pm. -20 21 * * * /path/to/scripts/smack-my-bitch-up.sh >> /path/to/smack-my-bitch-up.log 2>&1 +# Runs `smack-my-bitch-up.sh` monday to friday at 9:20 pm. +20 21 * * 1-5 /path/to/scripts/smack-my-bitch-up.sh >> /path/to/smack-my-bitch-up.log 2>&1 -# Runs `hangover.sh` daily at 8:45 am. -45 8 * * * /path/to/scripts/hangover.sh >> /path/to/hangover.log 2>&1 +# Runs `hangover.sh` monday to friday at 8:45 am. +45 8 * * 1-5 /path/to/scripts/hangover.sh >> /path/to/hangover.log 2>&1 # Runs `kumar-asshole.sh` every 10 minutes. */10 * * * * /path/to/scripts/kumar-asshole.sh -# Runs `fucking-coffee.sh` hourly from 9am to 6pm. -0 9-18 * * * /path/to/scripts/fucking-coffee.sh +# Runs `fucking-coffee.sh` hourly from 9am to 6pm on weekdays. +0 9-18 * * 1-5 /path/to/scripts/fucking-coffee.sh ``` --- diff --git a/fucking_coffee.rb b/fucking_coffee.rb index 29564be8..69a85ab1 100755 --- a/fucking_coffee.rb +++ b/fucking_coffee.rb @@ -1,8 +1,5 @@ #!/usr/bin/env ruby -# Skip on weekends -exit if Time.now.saturday? || Time.now.sunday? - # Exit early if no sessions with my username are found exit unless `who -q`.include? ENV['USER'] diff --git a/hangover.rb b/hangover.rb index 400c0d81..8578aaf8 100755 --- a/hangover.rb +++ b/hangover.rb @@ -1,8 +1,5 @@ #!/usr/bin/env ruby -# Skip on weekends -exit if Time.now.saturday? || Time.now.sunday? - # Exit early if sessions with my username are found exit if `who -q`.include? ENV['USER'] diff --git a/hangover.sh b/hangover.sh index fb3b7243..800a182a 100755 --- a/hangover.sh +++ b/hangover.sh @@ -1,12 +1,5 @@ #!/bin/sh -e -DAYOFWEEK=$(date +%u) - -# Skip on weekends -if [ "$DAYOFWEEK" -eq 6 ] || [ "$DAYOFWEEK" -eq 7 ]; then - exit -fi - # Exit early if any session with my username is found if who | grep -wq $USER; then exit diff --git a/python/fucking_coffee.py b/python/fucking_coffee.py index a510b028..c19572f3 100755 --- a/python/fucking_coffee.py +++ b/python/fucking_coffee.py @@ -1,17 +1,10 @@ #!/usr/bin/env python -import datetime import sys import subprocess import telnetlib import time -today = datetime.date.today() - -# skip weekends -if today.strftime('%A') in ('Saturday', 'Sunday'): - sys.exit() - # exit if no sessions with my username are found output = subprocess.check_output('who') if 'my_username' not in output: diff --git a/python/hangover.py b/python/hangover.py index 1daab656..b1903cd9 100755 --- a/python/hangover.py +++ b/python/hangover.py @@ -1,18 +1,11 @@ #!/usr/bin/env python -import datetime import os import random from twilio.rest import TwilioRestClient from time import strftime import subprocess -today = datetime.date.today() - -# skip weekends -if today.strftime('%A') in ('Saturday', 'Sunday'): - sys.exit() - # exit if sessions with my username are found output = subprocess.check_output('who') if 'my_username' in output: diff --git a/python/smack_my_bitch_up.py b/python/smack_my_bitch_up.py index 08844161..5a5d4250 100755 --- a/python/smack_my_bitch_up.py +++ b/python/smack_my_bitch_up.py @@ -1,6 +1,5 @@ #!/usr/bin/env python -import datetime import os import random from twilio.rest import TwilioRestClient @@ -8,13 +7,6 @@ import sys from time import strftime - -today = datetime.date.today() - -# skip weekends -if today.strftime('%A') == 'Saturday' || today('%A') == 'Sunday': - sys.exit() - # exit if no sessions with my username are found output = subprocess.check_output('who') if 'my_username' not in output: diff --git a/python3/fucking_coffee.py b/python3/fucking_coffee.py index e213a3d0..0268b79a 100755 --- a/python3/fucking_coffee.py +++ b/python3/fucking_coffee.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -import datetime import telnetlib import time @@ -13,10 +12,6 @@ def main(): - # Skip on weekends. - if datetime.date.today().weekday() in (0, 6,): - return - # Exit early if no sessions with my_username are found. if not any(s.startswith(b'my_username ') for s in sh('who').split(b'\n')): return diff --git a/python3/hangover.py b/python3/hangover.py index 744b9593..25ac0faa 100755 --- a/python3/hangover.py +++ b/python3/hangover.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -import datetime import random from twilio import TwilioRestException @@ -18,10 +17,6 @@ def main(): - # Skip on weekends. - if datetime.date.today().weekday() in (0, 6,): - return - # Exit early if any session with my_username is found. if any(s.startswith(b'my_username ') for s in sh('who').split(b'\n')): return diff --git a/python3/smack_my_bitch_up.py b/python3/smack_my_bitch_up.py index dce950d8..f160c1c0 100755 --- a/python3/smack_my_bitch_up.py +++ b/python3/smack_my_bitch_up.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -import datetime import random from twilio import TwilioRestException @@ -18,10 +17,6 @@ def main(): - # Skip on weekends. - if datetime.date.today().weekday() in (0, 6,): - return - # Exit early if no sessions with my_username are found. if not any(s.startswith(b'my_username ') for s in sh('who').split(b'\n')): return diff --git a/smack-my-bitch-up.sh b/smack-my-bitch-up.sh index b0bf6b19..cc0547c1 100755 --- a/smack-my-bitch-up.sh +++ b/smack-my-bitch-up.sh @@ -1,12 +1,5 @@ #!/bin/sh -e -DAYOFWEEK=$(date +%u) - -# Skip on weekends -if [ "$DAYOFWEEK" -eq 6 ] || [ "$DAYOFWEEK" -eq 7 ]; then - exit -fi - # Exit early if no sessions with my username are found if ! who | grep -wq $USER; then exit diff --git a/smack_my_bitch_up.rb b/smack_my_bitch_up.rb index 06596e83..e970f2cc 100755 --- a/smack_my_bitch_up.rb +++ b/smack_my_bitch_up.rb @@ -1,8 +1,5 @@ #!/usr/bin/env ruby -# Skip on weekends -exit if Time.now.saturday? || Time.now.sunday? - # Exit early if no sessions with my username are found exit if `who -q`.include? ENV['USER'] From 95a25f20ea8a86e5315c7ce20336b83f8c56814a Mon Sep 17 00:00:00 2001 From: hzwanghonglai Date: Fri, 27 Nov 2015 16:10:43 +0800 Subject: [PATCH 05/63] fucking coffee using coffeescript --- coffee/fucking.coffee | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100755 coffee/fucking.coffee diff --git a/coffee/fucking.coffee b/coffee/fucking.coffee new file mode 100755 index 00000000..d0f26bca --- /dev/null +++ b/coffee/fucking.coffee @@ -0,0 +1,28 @@ +#!/usr/bin/env coffee + +username = 'name' + +host = 'localhost' +port = '3000' +pass = '5555' + +sh = require('child_process').execSync + +# weekend +process.exit 0 if new Date().getDay() in [6, 0] + +# no sessions +process.exit 0 unless new RegExp(username).test sh('who -q').toString() + +conn = require('net').createConnection(port, host) + +setTimeout -> + conn.write "#{pass}\nsys brew\n" + setTimeout -> + conn.end 'sys pour' + process.exit(0) + , 2 * 1000 +, 1 * 1000 + +# alert +sh('say come here and take your fucking coffee') From 560667284820b8893c258565d801e21bb5e9d21e Mon Sep 17 00:00:00 2001 From: Maxime Orefice Date: Fri, 27 Nov 2015 11:32:10 +0100 Subject: [PATCH 06/63] Update smack_my_bitch_up.rb Correct exit session unless session with username is found --- smack_my_bitch_up.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/smack_my_bitch_up.rb b/smack_my_bitch_up.rb index 06596e83..61648947 100755 --- a/smack_my_bitch_up.rb +++ b/smack_my_bitch_up.rb @@ -4,7 +4,7 @@ exit if Time.now.saturday? || Time.now.sunday? # Exit early if no sessions with my username are found -exit if `who -q`.include? ENV['USER'] +exit unless `who -q`.include? ENV['USER'] require 'dotenv' require 'twilio-ruby' From 3bcd684b06d41a068282e0bdb6588702686de452 Mon Sep 17 00:00:00 2001 From: robaganrab Date: Fri, 27 Nov 2015 15:43:13 +0100 Subject: [PATCH 07/63] Add perl/smack-my-bitch-up.pl Dependencies: - DateTime - SMS::Send::Twilio - YAML --- perl/smack-my-bitch-up.pl | 72 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100755 perl/smack-my-bitch-up.pl diff --git a/perl/smack-my-bitch-up.pl b/perl/smack-my-bitch-up.pl new file mode 100755 index 00000000..47075186 --- /dev/null +++ b/perl/smack-my-bitch-up.pl @@ -0,0 +1,72 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use DateTime; +use SMS::Send; +use YAML; + +# Config +my $conf = Load( <<'...' ); +--- +phone_numbers: + my_number: +15005550006 + her_number: +xxx +reasons: + - Working hard + - Gotta ship this feature + - Someone fucked the system again +... + +my $date = DateTime->now; + +# Skip on weekends +if ( $date->day_of_week >= 6 ) { + exit; +} + +# Exit early if no sessions with my username are found +open( my $cmd_who, '-|', 'who' ) || die "Cannot pipe who command ". $!; + +my @sessions = grep { + m/$ENV{'USER'}/ +} <$cmd_who>; + +close $cmd_who; + +exit if ( scalar( @sessions ) == 0 ); + +# Load Twilio API config +open( my $env, '<', '../.env' ) || die "Cannot find .env file in project root."; +LINE: while ( my $line = <$env> ) { + next LINE unless ( $line =~ m/^(TWILIO[^=]+)=(.*)(?:[\n\r]*)/ ); + $conf->{'env'}->{ $1 } = $2; +} + +close $env; + +# Randomize excuse +my $reason_number = int( rand( scalar( @{ $conf->{'reasons'} } ) ) ); +my $sms_text = "Late at work. ". $conf->{'reasons'}[ $reason_number ]; + +# Create an object. There are three required values: +my $sender = SMS::Send->new('Twilio', + _accountsid => $conf->{'env'}->{'TWILIO_ACCOUNT_SID'}, + _authtoken => $conf->{'env'}->{'TWILIO_AUTH_TOKEN'}, + _from => $conf->{'phone_numbers'}->{'my_number'}, +); + +# Send a message to me +my $sent = $sender->send_sms( + text => $sms_text, + to => $conf->{'phone_numbers'}->{'her_number'}, +); + +# Did it send? +if ( $sent ) { + print "Sent message.\n"; +} else { + print "Message failed.\n"; +} + From 4e17743407dc2b3eb5d0f1b5dc8d5d8620571698 Mon Sep 17 00:00:00 2001 From: robaganrab Date: Fri, 27 Nov 2015 15:44:17 +0100 Subject: [PATCH 08/63] Add perl/hangover.pl Dependencies: - DateTime - SMS::Send::Twilio - YAML --- perl/hangover.pl | 73 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100755 perl/hangover.pl diff --git a/perl/hangover.pl b/perl/hangover.pl new file mode 100755 index 00000000..dda41a95 --- /dev/null +++ b/perl/hangover.pl @@ -0,0 +1,73 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use DateTime; +use SMS::Send; +use YAML; + +# Config +my $conf = Load( <<'...' ); +--- +phone_numbers: + my_number: +15005550006 + boss_number: +xxx +reasons: + - Locked out + - Pipes broke + - Food poisoning + - Not feeling well +... + +my $date = DateTime->now; + +# Skip on weekends +if ( $date->day_of_week >= 6 ) { + exit; +} + +# Exit early if no sessions with my username are found +open( my $cmd_who, '-|', 'who' ) || die "Cannot pipe who command ". $!; + +my @sessions = grep { + m/$ENV{'USER'}/ +} <$cmd_who>; + +close $cmd_who; + +exit if ( scalar( @sessions ) == 0 ); + +# Load Twilio API config +open( my $env, '<', '../.env' ) || die "Cannot find .env file in project root."; +LINE: while ( my $line = <$env> ) { + next LINE unless ( $line =~ m/^(TWILIO[^=]+)=(.*)(?:[\n\r]*)/ ); + $conf->{'env'}->{ $1 } = $2; +} + +close $env; + +# Randomize excuse +my $reason_number = int( rand( scalar( @{ $conf->{'reasons'} } ) ) ); +my $sms_text = "Gonna work from home. ". $conf->{'reasons'}[ $reason_number ]; + +# Create an object. There are three required values: +my $sender = SMS::Send->new('Twilio', + _accountsid => $conf->{'env'}->{'TWILIO_ACCOUNT_SID'}, + _authtoken => $conf->{'env'}->{'TWILIO_AUTH_TOKEN'}, + _from => $conf->{'phone_numbers'}->{'my_number'}, +); + +# Send a message to me +my $sent = $sender->send_sms( + text => $sms_text, + to => $conf->{'phone_numbers'}->{'boss_number'}, +); + +# Did it send? +if ( $sent ) { + print "Sent message.\n"; +} else { + print "Message failed.\n"; +} + From c7bce5514c54f0f615a84aeb7f0085f74b40b933 Mon Sep 17 00:00:00 2001 From: robaganrab Date: Fri, 27 Nov 2015 15:45:12 +0100 Subject: [PATCH 09/63] Add perl/fucking-coffee.pl Dependencies: - DateTime - Net::Telnet - YAML --- perl/fucking-coffee.pl | 49 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100755 perl/fucking-coffee.pl diff --git a/perl/fucking-coffee.pl b/perl/fucking-coffee.pl new file mode 100755 index 00000000..bc08054d --- /dev/null +++ b/perl/fucking-coffee.pl @@ -0,0 +1,49 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use DateTime; +use YAML; +use Net::Telnet; + +# Config +my $conf = Load( <<'...' ); +--- +coffee_machine_ip: 10.10.42.42 +password: 1234 +password_prompt: Password: +delay_before_brew: 17 +delay: 24 +... + +# Skip on weekends +my $date = DateTime->now; +if ( $date->day_of_week >= 6 ) { + exit; +} + +# Exit early if no sessions with my username are found +open( my $cmd_who, '-|', 'who' ) || die "Cannot pipe who command ". $!; + +my @sessions = grep { + m/$ENV{'USER'}/ +} <$cmd_who>; + +close $cmd_who; + +exit if ( scalar( @sessions ) == 0 ); + +sleep $conf->{'delay_before_brew'}; + +my $con = Net::Telnet->new( + 'Host' => $conf->{'coffee_machine_ip'}, +); + +$con->watifor( $conf->{'password_prompt'} ); +$con->cmd( $conf->{'password'} ); +$con->cmd( 'sys brew' ); +sleep $conf->{'delay'}; +$con->cmd( 'sys pour' ); +$con->close; + From 3c4205c43f13709ff05244de7fc72c9dc4759446 Mon Sep 17 00:00:00 2001 From: robaganrab Date: Fri, 27 Nov 2015 15:46:03 +0100 Subject: [PATCH 10/63] Add perl/kumar-asshole.pl Dependencies: - DateTime - Mail::Webmail::Gmail - YAML TODO: Rewrite using a different GMail interface. --- perl/kumar-asshole.pl | 88 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100755 perl/kumar-asshole.pl diff --git a/perl/kumar-asshole.pl b/perl/kumar-asshole.pl new file mode 100755 index 00000000..06db753f --- /dev/null +++ b/perl/kumar-asshole.pl @@ -0,0 +1,88 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use YAML; +use DateTime; +use Mail::Webmail::Gmail; + +# Config +my $conf = Load( <<'...' ); +--- +kumar_mail: kumar.a@examle.com +database_regex: \S+_staging +keywords_regex: sorry|help|wrong +backup_path: /home/backups/databases/ +... +$conf->{'database_regex'} = qr/ ( $conf->{'database_regex'} ) /x; +$conf->{'keywords_regex'} = qr/ ( $conf->{'keywords_regex'} ) /x; + +my $date = DateTime->now->subtract( + 'days' => 1 +); + +# Load GMail API config +open( my $env, '<', '../.env' ) || die "Cannot find .env file in project root."; +LINE: while ( my $line = <$env> ) { + next LINE unless ( $line =~ m/^(GMAIL[^=]+)=(.*)(?:[\n\r]*)/ ); + $conf->{'env'}->{ $1 } = $2; +} + +close $env; + +my $gmail = Mail::Webmail::Gmail->new( + username => $conf->{'env'}->{'GMAIL_USERNAME'}, + password => $conf->{'env'}->{'GMAIL_PASSWORD'}, + encrypt_session => 1, +); + +my $messages = $gmail->get_messages( label => $Mail::Webmail::Gmail::FOLDERS{ 'INBOX' } ); +die "Cannot fetch emails: ". $gmail->error_msg(); + +MESSAGE: foreach my $message ( @{ $messages } ) { + unless ( + ( $message->{ 'new' } ) + && ( $message->{'sender_email'} eq $conf->{'kumars_email'} ) + && ( $message->{'body'} =~ m/$conf->{'keywords_regex'}/ ) + && ( $message->{'body'} =~ m/$conf->{'database_regex'}/ ) + ) { + print "Skipping mail from=[". $message->{'sender_email'}."] subject=[". $message->{'subject'} ."]\n"; + next MESSAGE; + } + exit 1; + + my $database = $1; + my $backup_file = $conf->{'backup_path'} . $database .'-'. $date->ymd() .'.gz'; + + unless ( -f $backup_file ) { + die 'Cannot find backup file=['. $backup_file ."]\n"; + } + + print 'Restoring database=['. $database .'] from day=['. $date->ymd() .'] from file=['. $backup_file ."]\n"; + + # Restore DB + system( 'gunzip -c '. $backup_file .' | psql '. $database ); + die "Error while restoring the database=[". $database ."] from file=[". $backup_file ."]" if ( $? >> 8 ); + + # Mark as read, add label, reply + $gmail->edit_labels( + 'label' => 'Database fixes', + 'action' => 'add', + 'msgid' => $message->{'id'} + ); + + $gmail->send_message( + 'to' => $conf->{'kumars_email'}, + 'subject' => 'RE: '. $message->{'subject'}, + 'msgbody' => "No problem. I've fixed it. \n\n Please be careful next time.", + ); + + $gmail->edit_labels( + 'label' => 'unread', + 'action' => 'remove', + 'msgid' => $message->{'id'} + ); + +} + From a1716b803fe8496c9fcd7d455cc4e8ed30fd8f7d Mon Sep 17 00:00:00 2001 From: Nihad Abbasov Date: Fri, 27 Nov 2015 22:01:08 +0400 Subject: [PATCH 11/63] fix ruby script closes #53 --- kumar_asshole.rb | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/kumar_asshole.rb b/kumar_asshole.rb index ca5b9f6b..fc6a2f0e 100755 --- a/kumar_asshole.rb +++ b/kumar_asshole.rb @@ -14,8 +14,16 @@ DB_NAME_REGEX = /\S+_staging/ KEYWORDS_REGEX = /sorry|help|wrong/i +def create_reply(subject) + gmail.compose do + to kumars_email + subject "RE: #{subject}" + body "No problem. I've fixed it. \n\n Please be careful next time." + end +end + gmail.inbox.find(:unread, from: kumars_email).each do |email| - if email.body[KEYWORDS_REGEX] && (db_name = email.body[DB_NAME_REGEX]) + if email.body.raw_source[KEYWORDS_REGEX] && (db_name = email.body.raw_source[DB_NAME_REGEX]) backup_file = "/home/backups/databases/#{db_name}-" + (Date.today - 1).strftime('%Y%m%d') + '.gz' abort 'ERROR: Backup file not found' unless File.exist?(backup_file) @@ -29,11 +37,3 @@ gmail.deliver(reply) end end - -def create_reply(subject) - gmail.compose do - to kumars_email - subject "RE: #{subject}" - body "No problem. I've fixed it. \n\n Please be careful next time." - end -end From ac6edc54a8ce4b6d5abb8408723b42a5226fa7da Mon Sep 17 00:00:00 2001 From: mhsjlw Date: Tue, 24 Nov 2015 20:12:54 -0500 Subject: [PATCH 12/63] The coffee machines uses telnet not SSH Update the TCP socket Oops! Fix a grammar mistake --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1a34a218..bfda095d 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ story](https://www.jitbit.com/alexblog/249-now-thats-what-i-call-a-hacker/)_: > xxx: [`hangover.sh`](https://github.com/NARKOZ/hacker-scripts/blob/master/hangover.sh) - another cron-job that is set to specific dates. Sends automated emails like "not feeling well/gonna work from home" etc. Adds a random "reason" from another predefined array of strings. Fires if there are no interactive sessions on the server at 8:45am. -> xxx: (and the oscar goes to) [`fucking-coffee.sh`](https://github.com/NARKOZ/hacker-scripts/blob/master/fucking-coffee.sh) - this one waits exactly 17 seconds (!), then opens an SSH session to our coffee-machine (we had no frikin idea the coffee machine is on the network, runs linux and has SSHD up and running) and sends some weird gibberish to it. Looks binary. Turns out this thing starts brewing a mid-sized half-caf latte and waits another 24 (!) seconds before pouring it into a cup. The timing is exactly how long it takes to walk to the machine from the dudes desk. +> xxx: (and the oscar goes to) [`fucking-coffee.sh`](https://github.com/NARKOZ/hacker-scripts/blob/master/fucking-coffee.sh) - this one waits exactly 17 seconds (!), then opens a telnet session to our coffee-machine (we had no frikin idea the coffee machine is on the network, runs linux and has a TCP socket up and running) and sends something like `sys brew`. Turns out this thing starts brewing a mid-sized half-caf latte and waits another 24 (!) seconds before pouring it into a cup. The timing is exactly how long it takes to walk to the machine from the dudes desk. > xxx: holy sh*t I'm keeping those From 4334409f2045c56aa546c20fc31aa4936bb1eabb Mon Sep 17 00:00:00 2001 From: bitsapien Date: Sat, 28 Nov 2015 11:26:22 +0530 Subject: [PATCH 13/63] fixed issue with gmail, kumars_email variable scope --- kumar_asshole.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/kumar_asshole.rb b/kumar_asshole.rb index fc6a2f0e..0dc5cb7c 100755 --- a/kumar_asshole.rb +++ b/kumar_asshole.rb @@ -8,21 +8,21 @@ GMAIL_USERNAME = ENV['GMAIL_USERNAME'] GMAIL_PASSWORD = ENV['GMAIL_PASSWORD'] -gmail = Gmail.connect(GMAIL_USERNAME, GMAIL_PASSWORD) -kumars_email = 'kumar.a@example.com' +GMAIL = Gmail.connect(GMAIL_USERNAME, GMAIL_PASSWORD) +KUMARS_EMAIL = 'kumar.a@example.com' DB_NAME_REGEX = /\S+_staging/ KEYWORDS_REGEX = /sorry|help|wrong/i def create_reply(subject) - gmail.compose do - to kumars_email + GMAIL.compose do + to KUMARS_EMAIL subject "RE: #{subject}" body "No problem. I've fixed it. \n\n Please be careful next time." end end -gmail.inbox.find(:unread, from: kumars_email).each do |email| +GMAIL.inbox.find(:unread, from: KUMARS_EMAIL).each do |email| if email.body.raw_source[KEYWORDS_REGEX] && (db_name = email.body.raw_source[DB_NAME_REGEX]) backup_file = "/home/backups/databases/#{db_name}-" + (Date.today - 1).strftime('%Y%m%d') + '.gz' abort 'ERROR: Backup file not found' unless File.exist?(backup_file) @@ -34,6 +34,6 @@ def create_reply(subject) email.read! email.label('Database fixes') reply = create_reply(email.subject) - gmail.deliver(reply) + GMAIL.deliver(reply) end end From 213ee55d77f5af275602752c49f666c60382a835 Mon Sep 17 00:00:00 2001 From: Alexander Vega Date: Sat, 28 Nov 2015 20:58:18 -0500 Subject: [PATCH 14/63] Error on line 33 Error resulting in missing underscore after "from" on line 33 --- python/smack_my_bitch_up.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/smack_my_bitch_up.py b/python/smack_my_bitch_up.py index 5a5d4250..02c7e051 100755 --- a/python/smack_my_bitch_up.py +++ b/python/smack_my_bitch_up.py @@ -30,7 +30,7 @@ client.messages.create( to=her_number, - from=my_number, + from_=my_number, body="Late at work. " + random.choice(reasons) ) From 98cb98919f359b03df9f32e471f0b94d6b48f88d Mon Sep 17 00:00:00 2001 From: Zen Laboratory Date: Sun, 29 Nov 2015 04:04:28 +0100 Subject: [PATCH 15/63] Update kumar-asshole.pl --- perl/kumar-asshole.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/perl/kumar-asshole.pl b/perl/kumar-asshole.pl index 06db753f..af7a4d83 100755 --- a/perl/kumar-asshole.pl +++ b/perl/kumar-asshole.pl @@ -10,7 +10,7 @@ # Config my $conf = Load( <<'...' ); --- -kumar_mail: kumar.a@examle.com +kumar_mail: kumar.a@example.com database_regex: \S+_staging keywords_regex: sorry|help|wrong backup_path: /home/backups/databases/ From 480bb625b61f477f50fe18e49e3e4e795ffaa701 Mon Sep 17 00:00:00 2001 From: Samir Madhavan Date: Mon, 30 Nov 2015 01:34:38 +0530 Subject: [PATCH 16/63] R version: smack_my_bitch_up.R --- R/smack_my_bitch_up.R | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 R/smack_my_bitch_up.R diff --git a/R/smack_my_bitch_up.R b/R/smack_my_bitch_up.R new file mode 100644 index 00000000..7257f88e --- /dev/null +++ b/R/smack_my_bitch_up.R @@ -0,0 +1,34 @@ +library(httr) + +today = Sys.Date() + +# skip weekends +if( weekdays(today) %in% c('Saturday','Sunday') ){ + quit() + } + +# exit if no sessions with my username are found +output = system("who", intern = TRUE) +if( !( grep('^my_user_name', output) ) ){ + quit() + } + +# returns 'None' if the key doesn't exist +TWILIO_ACCOUNT_SID = Sys.getenv('TWILIO_ACCOUNT_SID') +TWILIO_AUTH_TOKEN = Sys.getenv('TWILIO_AUTH_TOKEN') + +# Phone numbers +my_number = '+xxx' +her_number = '+xxx' + +reasons = c( + 'Working hard', + 'Gotta ship this feature', + 'Someone fucked the system again' + ) + +POST(paste("https://api.twilio.com/2010-04-01/Accounts/",TWILIO_ACCOUNT_SID,"/Messages.json",sep=""), + body = list(From=my_number,To=her_number,Body=sample(reasons,1) ), + authenticate(TWILIO_ACCOUNT_SID,TWILIO_AUTH_TOKEN) ) + +print( paste("Message sent at",Sys.time()) ) From a60ed71883d1c393ee90a2c7cbffafddda8c1c19 Mon Sep 17 00:00:00 2001 From: alexesprit Date: Sun, 29 Nov 2015 23:26:33 +0300 Subject: [PATCH 17/63] Proper check if user is logged in --- powershell/smack_my_bitch_up.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powershell/smack_my_bitch_up.ps1 b/powershell/smack_my_bitch_up.ps1 index 46c3d8f4..7b30b275 100644 --- a/powershell/smack_my_bitch_up.ps1 +++ b/powershell/smack_my_bitch_up.ps1 @@ -6,7 +6,7 @@ if ($DAYOFWEEK -eq 6 -or $DAYOFWEEK -eq 7) { } # Exit early if no sessions with my username are found -if ((QWINSTA $env:USERNAME | measure).Count -gt 0){ +if (-not (QWINSTA | FINDSTR $env:USERNAME)) { return } From ab3d6612126cdd2f6423893dea2241a7972c5f06 Mon Sep 17 00:00:00 2001 From: alexesprit Date: Mon, 30 Nov 2015 00:08:19 +0300 Subject: [PATCH 18/63] Fix sms sending When post data is set as text string, some characters like `plus` were not escaped. --- powershell/smack_my_bitch_up.ps1 | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/powershell/smack_my_bitch_up.ps1 b/powershell/smack_my_bitch_up.ps1 index 7b30b275..8b690bd4 100644 --- a/powershell/smack_my_bitch_up.ps1 +++ b/powershell/smack_my_bitch_up.ps1 @@ -14,9 +14,6 @@ if (-not (QWINSTA | FINDSTR $env:USERNAME)) { $MY_NUMBER='+xxx' $HER_NUMBER='+xxx' -$TWILIO_ACCOUNT_SID = 'xxx' -$TWILIO_AUTH_TOKEN = 'xxx' - $REASONS= 'Working hard', 'Gotta ship this feature', @@ -26,14 +23,18 @@ $RAND = Get-Random -Maximum $REASONS.Count $MSG="Late at work. $REASONS[$RAND]" +$API_URL = "https://api.twilio.com/2010-04-01/Accounts/$env:TWILIO_ACCOUNT_SID/Messages" +$BASE64AUTHINFO = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $env:TWILIO_ACCOUNT_SID,$env:TWILIO_AUTH_TOKEN))) +$body = @{ + From = $MY_NUMBER; + To = $HER_NUMBER; + Body = $MSG; +} -$BASE64AUTHINFO = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $TWILIO_ACCOUNT_SID,$TWILIO_AUTH_TOKEN))) - -#Send a text messag and Log errors +#Send a text message and Log errors try{ - Invoke-RestMethod -Method Post -Headers @{Authorization=("Basic {0}" -f $BASE64AUTHINFO)} "https://api.twilio.com/2010-04-01/Accounts/$TWILIO_ACCOUNT_SID/Messages" -Body "From=$MY_NUMBER&To=$HER_NUMBER&Body=$MSG" > $null + Invoke-RestMethod -Method Post -Headers @{Authorization=("Basic {0}" -f $BASE64AUTHINFO)} $API_URL -Body $body > $null } catch{ Write-Host "Failed to send SMS: $_" } - From fedb6faca1eff58b627739e833eb99557b5af197 Mon Sep 17 00:00:00 2001 From: alexesprit Date: Mon, 30 Nov 2015 00:19:03 +0300 Subject: [PATCH 19/63] Get random reason easier --- powershell/smack_my_bitch_up.ps1 | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/powershell/smack_my_bitch_up.ps1 b/powershell/smack_my_bitch_up.ps1 index 8b690bd4..903bd5cd 100644 --- a/powershell/smack_my_bitch_up.ps1 +++ b/powershell/smack_my_bitch_up.ps1 @@ -14,21 +14,19 @@ if (-not (QWINSTA | FINDSTR $env:USERNAME)) { $MY_NUMBER='+xxx' $HER_NUMBER='+xxx' -$REASONS= +$REASONS = 'Working hard', 'Gotta ship this feature', 'Someone fucked the system again' - -$RAND = Get-Random -Maximum $REASONS.Count - -$MSG="Late at work. $REASONS[$RAND]" +$reason = $REASONS | Get-Random +$message = "Late at work. $reason." $API_URL = "https://api.twilio.com/2010-04-01/Accounts/$env:TWILIO_ACCOUNT_SID/Messages" $BASE64AUTHINFO = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $env:TWILIO_ACCOUNT_SID,$env:TWILIO_AUTH_TOKEN))) $body = @{ From = $MY_NUMBER; To = $HER_NUMBER; - Body = $MSG; + Body = $message; } #Send a text message and Log errors From 793c49a6df46afd4549da8f2cb2dadb506f894c0 Mon Sep 17 00:00:00 2001 From: Ahmad Samiei Date: Mon, 30 Nov 2015 14:14:35 +0800 Subject: [PATCH 20/63] keep things simple --- php/composer.json | 5 ++ php/fucking_coffee.php | 177 +++-------------------------------------- 2 files changed, 16 insertions(+), 166 deletions(-) create mode 100644 php/composer.json diff --git a/php/composer.json b/php/composer.json new file mode 100644 index 00000000..fb100729 --- /dev/null +++ b/php/composer.json @@ -0,0 +1,5 @@ +{ + "require": { + "bestnetwork/telnet": "^1.0" + } +} diff --git a/php/fucking_coffee.php b/php/fucking_coffee.php index 5ab70c78..cbce3982 100644 --- a/php/fucking_coffee.php +++ b/php/fucking_coffee.php @@ -1,170 +1,15 @@ +#!/usr/bin/env php IsWeekend( date('m.d.y') ) == false ) - { - - return false; - } - - /** - * Create a new telnet class - */ - - $this->telnet = new Telnet( $this->host, $this->port ); - - /** - * Once we have completed this, we can brew our coffee! - */ - - $this->BrewCoffee( function(){ - - /** - * Echo out a message - */ - - echo "coffee has been poured"; - - /** - * Unset - */ - - unset( $this->telnet ); - }); - - /** - * Return tue - */ - - return true; - } - - /** - * Brews our coffee - * - * @param $callback - */ - - public function BrewCoffee( $callback ) - { - - if( $this->telnet != null ) - { - - /** - * Execute and enter the password - */ - - $this->telnet->exec('Password: ' . $this->password); - - /** - * Brew the coffee - */ - - $this->telnet->exec('sys brew'); - - /** - * Wait - */ - - sleep( $this->delay ); - - /** - * Pour the coffee - */ - - $this->telnet->exec('sys pour'); - - /** - * Execute our callback - */ - - call_user_func( $callback ); - } - } - - /** - * Is this currently the weekend? - * - * @param $date - * - * @return bool - */ - - public function IsWeekend( $date ) - { - - if( date('N', strtotime( $date ) ) >= 6 ) - { - - return true; - } - - return false; - } - -} \ No newline at end of file +(date('N') < 6) or exit('weekend'); +(strpos(exec('who'), getenv('USER')) !== false) or exit('no session'); +sleep(17); +$con = new TelnetClient('10.10.42.42'); +$con->execute('1234', 'Password: '); +$con->execute('sys brew'); +sleep(24); +$con->execute('sys pour'); \ No newline at end of file From 752e1c28eafb40df0dd27ad8e9af10c2e85cc084 Mon Sep 17 00:00:00 2001 From: Ahmad Samiei Date: Mon, 30 Nov 2015 14:15:07 +0800 Subject: [PATCH 21/63] lib added to composer --- php/Lib/Telnet.php | 264 --------------------------------------------- 1 file changed, 264 deletions(-) delete mode 100644 php/Lib/Telnet.php diff --git a/php/Lib/Telnet.php b/php/Lib/Telnet.php deleted file mode 100644 index 3409dc3a..00000000 --- a/php/Lib/Telnet.php +++ /dev/null @@ -1,264 +0,0 @@ - - * Based on the code originally written by Marc Ennaji and extended by - * Matthias Blaser - * - * Extended by Christian Hammers - * Modified by Frederik Sauer - * - */ - -class Telnet { - - private $host; - private $port; - private $timeout; - private $stream_timeout_sec; - private $stream_timeout_usec; - - private $socket = NULL; - private $buffer = NULL; - private $prompt; - private $errno; - private $errstr; - private $strip_prompt = TRUE; - - private $NULL; - private $DC1; - private $WILL; - private $WONT; - private $DO; - private $DONT; - private $IAC; - - private $global_buffer = ''; - - const TELNET_ERROR = FALSE; - const TELNET_OK = TRUE; - - public function __construct($host = '127.0.0.1', $port = '23', $timeout = 10, $prompt = '$', $stream_timeout = 1) { - $this->host = $host; - $this->port = $port; - $this->timeout = $timeout; - $this->setPrompt($prompt); - $this->setStreamTimeout($stream_timeout); - - // set some telnet special characters - $this->NULL = chr(0); - $this->DC1 = chr(17); - $this->WILL = chr(251); - $this->WONT = chr(252); - $this->DO = chr(253); - $this->DONT = chr(254); - $this->IAC = chr(255); - - $this->connect(); - } - - public function __destruct() { - // clean up resources - $this->disconnect(); - $this->buffer = NULL; - $this->global_buffer = NULL; - } - - public function connect() { - // check if we need to convert host to IP - if (!preg_match('/([0-9]{1,3}\\.){3,3}[0-9]{1,3}/', $this->host)) { - $ip = gethostbyname($this->host); - - if ($this->host == $ip) { - throw new Exception("Cannot resolve $this->host"); - } else { - $this->host = $ip; - } - } - - // attempt connection - suppress warnings - $this->socket = @fsockopen($this->host, $this->port, $this->errno, $this->errstr, $this->timeout); - - if (!$this->socket) { - throw new Exception("Cannot connect to $this->host on port $this->port"); - } - - if (!empty($this->prompt)) { - $this->waitPrompt(); - } - - return self::TELNET_OK; - } - - public function disconnect() { - if ($this->socket) { - if (! fclose($this->socket)) { - throw new Exception("Error while closing telnet socket"); - } - $this->socket = NULL; - } - return self::TELNET_OK; - } - - public function exec($command, $add_newline = TRUE) { - $this->write($command, $add_newline); - $this->waitPrompt(); - return $this->getBuffer(); - } - - public function login($username, $password) { - try { - $this->setPrompt('login:'); - $this->waitPrompt(); - $this->write($username); - $this->setPrompt('Password:'); - $this->waitPrompt(); - $this->write($password); - $this->setPrompt(); - $this->waitPrompt(); - } catch (Exception $e) { - throw new Exception("Login failed."); - } - - return self::TELNET_OK; - } - - public function setPrompt($str = '$') { - return $this->setRegexPrompt(preg_quote($str, '/')); - } - - public function setRegexPrompt($str = '\$') { - $this->prompt = $str; - return self::TELNET_OK; - } - - public function setStreamTimeout($timeout) { - $this->stream_timeout_usec = (int)(fmod($timeout, 1) * 1000000); - $this->stream_timeout_sec = (int)$timeout; - } - - public function stripPromptFromBuffer($strip) { - $this->strip_prompt = $strip; - } // function stripPromptFromBuffer - - protected function getc() { - stream_set_timeout($this->socket, $this->stream_timeout_sec, $this->stream_timeout_usec); - $c = fgetc($this->socket); - $this->global_buffer .= $c; - return $c; - } - - public function clearBuffer() { - $this->buffer = ''; - } - - public function readTo($prompt) { - if (!$this->socket) { - throw new Exception("Telnet connection closed"); - } - - // clear the buffer - $this->clearBuffer(); - - $until_t = time() + $this->timeout; - do { - // time's up (loop can be exited at end or through continue!) - if (time() > $until_t) { - throw new Exception("Couldn't find the requested : '$prompt' within {$this->timeout} seconds"); - } - - $c = $this->getc(); - - if ($c === FALSE) { - if (empty($prompt)) { - return self::TELNET_OK; - } - throw new Exception("Couldn't find the requested : '" . $prompt . "', it was not in the data returned from server: " . $this->buffer); - } - - // Interpreted As Command - if ($c == $this->IAC) { - if ($this->negotiateTelnetOptions()) { - continue; - } - } - - // append current char to global buffer - $this->buffer .= $c; - - // we've encountered the prompt. Break out of the loop - if (!empty($prompt) && preg_match("/{$prompt}$/", $this->buffer)) { - return self::TELNET_OK; - } - - } while ($c != $this->NULL || $c != $this->DC1); - } - - public function write($buffer, $add_newline = TRUE) { - if (!$this->socket) { - throw new Exception("Telnet connection closed"); - } - - // clear buffer from last command - $this->clearBuffer(); - - if ($add_newline == TRUE) { - $buffer .= "\n"; - } - - $this->global_buffer .= $buffer; - if (!fwrite($this->socket, $buffer) < 0) { - throw new Exception("Error writing to socket"); - } - - return self::TELNET_OK; - } - - protected function getBuffer() { - // Remove all carriage returns from line breaks - $buf = preg_replace('/\r\n|\r/', "\n", $this->buffer); - // Cut last line from buffer (almost always prompt) - if ($this->strip_prompt) { - $buf = explode("\n", $buf); - unset($buf[count($buf) - 1]); - $buf = implode("\n", $buf); - } - return trim($buf); - } - - public function getGlobalBuffer() { - return $this->global_buffer; - } - - protected function negotiateTelnetOptions() { - $c = $this->getc(); - - if ($c != $this->IAC) { - if (($c == $this->DO) || ($c == $this->DONT)) { - $opt = $this->getc(); - fwrite($this->socket, $this->IAC . $this->WONT . $opt); - } else if (($c == $this->WILL) || ($c == $this->WONT)) { - $opt = $this->getc(); - fwrite($this->socket, $this->IAC . $this->DONT . $opt); - } else { - throw new Exception('Error: unknown control character ' . ord($c)); - } - } else { - throw new Exception('Error: Something Wicked Happened'); - } - - return self::TELNET_OK; - } - - protected function waitPrompt() { - return $this->readTo($this->prompt); - } -} \ No newline at end of file From 8788a761c52855fd96f640086bcfb1b91626ce03 Mon Sep 17 00:00:00 2001 From: Ahmad Samiei Date: Mon, 30 Nov 2015 14:16:52 +0800 Subject: [PATCH 22/63] no need to check date. handeled by cronjob --- php/fucking_coffee.php | 1 - 1 file changed, 1 deletion(-) diff --git a/php/fucking_coffee.php b/php/fucking_coffee.php index cbce3982..ea794ff8 100644 --- a/php/fucking_coffee.php +++ b/php/fucking_coffee.php @@ -5,7 +5,6 @@ use Bestnetwork\Telnet\TelnetClient; -(date('N') < 6) or exit('weekend'); (strpos(exec('who'), getenv('USER')) !== false) or exit('no session'); sleep(17); $con = new TelnetClient('10.10.42.42'); From 56259563d4db3e3bb158c56f850e274c88cbf08f Mon Sep 17 00:00:00 2001 From: Ahmad Samiei Date: Mon, 30 Nov 2015 14:20:05 +0800 Subject: [PATCH 23/63] oops! newline end of file. --- php/fucking_coffee.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/fucking_coffee.php b/php/fucking_coffee.php index ea794ff8..074e22fe 100644 --- a/php/fucking_coffee.php +++ b/php/fucking_coffee.php @@ -11,4 +11,4 @@ $con->execute('1234', 'Password: '); $con->execute('sys brew'); sleep(24); -$con->execute('sys pour'); \ No newline at end of file +$con->execute('sys pour'); From 7e9149e53c44bff6b37a1522a5363b10785d1279 Mon Sep 17 00:00:00 2001 From: arjunnambiartc Date: Mon, 30 Nov 2015 15:23:17 +0530 Subject: [PATCH 24/63] Ported hangover script to golang --- go/hangover.go | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 go/hangover.go diff --git a/go/hangover.go b/go/hangover.go new file mode 100644 index 00000000..12d5d3e2 --- /dev/null +++ b/go/hangover.go @@ -0,0 +1,47 @@ +package main + +import ( + "fmt" + "log" + "math/rand" + "os" + + "github.com/codeskyblue/go-sh" + "github.com/subosito/twilio" +) + +const my_number string = "+xxxxx" +const boss_number string = "+yyyyy" + +func main() { + //exit if sessions with my username are found + _, err := sh.Command("who").Command("grep", "my_username").Output() + if err != nil { + os.Exit(1) + } + + //Grab Twilio ID and token from environment variables + Account_Sid := os.Getenv("TWILIO_ACCOUNT_SID") + Auth_Token := os.Getenv("TWILIO_AUTH_TOKEN") + + //create the reasons slice and append reasons to it + reasons := make([]string, 0) + reasons = append(reasons, + "Locked out", + "Pipes broke", + "Food poisoning", + "Not feeling well") + + // Initialize Twilio client and send message + client := twilio.NewClient(Account_Sid, Auth_Token, nil) + message := fmt.Sprint("Gonna work from home...", reasons[rand.Intn(len(reasons))]) + + params := twilio.MessageParams{ + Body: message, + } + s, resp, err := client.Messages.Send(my_number, boss_number, params) + + if err == nil { + log.Fatal(s, resp, err) + } +} From 7ff2fc8b69bd8bba231282f3b2e34f8b35fc228c Mon Sep 17 00:00:00 2001 From: Lipis Date: Mon, 30 Nov 2015 11:13:27 +0100 Subject: [PATCH 25/63] Removed parenthesis for consistency --- coffee/fucking.coffee | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/coffee/fucking.coffee b/coffee/fucking.coffee index d0f26bca..8df9dbed 100755 --- a/coffee/fucking.coffee +++ b/coffee/fucking.coffee @@ -14,15 +14,15 @@ process.exit 0 if new Date().getDay() in [6, 0] # no sessions process.exit 0 unless new RegExp(username).test sh('who -q').toString() -conn = require('net').createConnection(port, host) +conn = require('net').createConnection port, host setTimeout -> conn.write "#{pass}\nsys brew\n" setTimeout -> conn.end 'sys pour' - process.exit(0) + process.exit 0 , 2 * 1000 , 1 * 1000 # alert -sh('say come here and take your fucking coffee') +sh 'say come here and take your fucking coffee' From 7c5686a11565a720348b15034b0b8cdd45f82329 Mon Sep 17 00:00:00 2001 From: Anubhav Singh Date: Mon, 30 Nov 2015 21:21:04 +0530 Subject: [PATCH 26/63] golang smacked my bitch up --- go/smack_my_bitch_up.go | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100755 go/smack_my_bitch_up.go diff --git a/go/smack_my_bitch_up.go b/go/smack_my_bitch_up.go new file mode 100755 index 00000000..fd4f68c7 --- /dev/null +++ b/go/smack_my_bitch_up.go @@ -0,0 +1,39 @@ +package main + +import( + "os/exec" + "fmt" + "strings" + "os" + "math/rand" + "time" + ) + +func main(){ + output1,err := exec.Command("who").Output() + output2 := os.Getenv("USER") + users := string(output1[:]) + current_user := string(output2[:]) + if(!strings.Contains(users,current_user)){ + return + } + + + reasons := []string {"Working hard","Gotta ship this feature","Someone fucked the system again"} + + rand.Seed(time.Now().UTC().UnixNano()) + message := "Late at work. " + reasons[rand.Intn(len(reasons))] + + TWILIO_ACCOUNT_SID := string(os.Getenv("TWILIO_ACCOUNT_SID")) + TWILIO_AUTH_TOKEN := string(os.Getenv("TWILIO_AUTH_TOKEN")) + MY_NUMBER := string(os.Getenv("MY_NUMBER")) + HER_NUMBER := string(os.Getenv("HER_NUMBER")) + + response,err := exec.Command("curl","-fSs","-u",TWILIO_ACCOUNT_SID + ":" + TWILIO_AUTH_TOKEN, "-d", "From=" + MY_NUMBER, "-d", "To=" + HER_NUMBER, "-d" , "Body=" + message, "https://api.twilio.com/2010-04-01/Accounts/" + TWILIO_ACCOUNT_SID + "/Messages").Output() + if(err != nil){ + fmt.Printf("Failed to send SMS: ",err.mess) + return + } + + fmt.Printf("Message Sent Successfully with response: %s ",response) +} From cb105c85aefa93072b3289aac1639cb90ddb0e4c Mon Sep 17 00:00:00 2001 From: Anubhav Singh Date: Tue, 1 Dec 2015 13:10:25 +0530 Subject: [PATCH 27/63] removed .mess bug of smack_my_bitch_up --- go/smack_my_bitch_up.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/smack_my_bitch_up.go b/go/smack_my_bitch_up.go index fd4f68c7..66f7311f 100755 --- a/go/smack_my_bitch_up.go +++ b/go/smack_my_bitch_up.go @@ -31,7 +31,7 @@ func main(){ response,err := exec.Command("curl","-fSs","-u",TWILIO_ACCOUNT_SID + ":" + TWILIO_AUTH_TOKEN, "-d", "From=" + MY_NUMBER, "-d", "To=" + HER_NUMBER, "-d" , "Body=" + message, "https://api.twilio.com/2010-04-01/Accounts/" + TWILIO_ACCOUNT_SID + "/Messages").Output() if(err != nil){ - fmt.Printf("Failed to send SMS: ",err.mess) + fmt.Printf("Failed to send SMS: ",err) return } From 66de802d293776ca0155aad9010fecd31dc3c068 Mon Sep 17 00:00:00 2001 From: Yudi Purwanto Date: Tue, 1 Dec 2015 16:31:24 +0700 Subject: [PATCH 28/63] require phpdotenv --- php/composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/php/composer.json b/php/composer.json index fb100729..376b4941 100644 --- a/php/composer.json +++ b/php/composer.json @@ -1,5 +1,6 @@ { "require": { - "bestnetwork/telnet": "^1.0" + "bestnetwork/telnet": "^1.0", + "vlucas/phpdotenv": "^2.0" } } From c989c42822b799286d67481747cb0f5ff2b4141e Mon Sep 17 00:00:00 2001 From: Yudi Purwanto Date: Tue, 1 Dec 2015 16:33:14 +0700 Subject: [PATCH 29/63] load phpenv --- php/fucking_coffee.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/php/fucking_coffee.php b/php/fucking_coffee.php index 074e22fe..071d1d71 100644 --- a/php/fucking_coffee.php +++ b/php/fucking_coffee.php @@ -3,6 +3,9 @@ require 'vendor/autoload.php'; +$dotenv = new Dotenv\Dotenv(__DIR__); +$dotenv->load(); + use Bestnetwork\Telnet\TelnetClient; (strpos(exec('who'), getenv('USER')) !== false) or exit('no session'); From 3ba12066fd315262159dc1375cba6022c96d7370 Mon Sep 17 00:00:00 2001 From: Akshay Kashyap Date: Tue, 1 Dec 2015 16:54:25 -0500 Subject: [PATCH 30/63] NodeJS Implementation Made executable NodeJS Implementation of fucking_coffee --- nodejs/fucking_coffee.js | 41 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 nodejs/fucking_coffee.js diff --git a/nodejs/fucking_coffee.js b/nodejs/fucking_coffee.js new file mode 100644 index 00000000..b30a6b4b --- /dev/null +++ b/nodejs/fucking_coffee.js @@ -0,0 +1,41 @@ +#!/usr/bin/env node + +/* Before running: + npm install telnet-client +*/ + +var exec = require('child_process').exec; +var telnet = require('telnet-client'); + +var me = 'my_username'; + +exec("who", function(error, stdout, stderr) { + + // Exit if no sessions with my username are found + if(stdout.indexOf(me) == -1) + process.exit(/*1*/); + + var coffee_machine_ip = 'xxx.xxx.xxx.xxx'; + var password = 'xxxx'; + var con = new telnet(); + + con.on('ready', function(prompt) { + con.exec('Password: ' + password, function(error, res) { + + // Brew Coffee! + con.exec('sys brew', function(error, res) { + + // Wait for 24s + setTimeout(function() { + + // Pour Coffee! + con.exec('sys pour', function(error, res) { + con.end(); + }); + }, 24000); + }); + }); + }); + + con.connect({host: coffee_machine_ip}); +}); From 7c9a8e9ab12b1f5f6ce8ac0c50d31bb7d7ac0361 Mon Sep 17 00:00:00 2001 From: Akshay Kashyap Date: Tue, 1 Dec 2015 22:09:12 -0500 Subject: [PATCH 31/63] NodeJS for hangover and smack_my_bitch_up --- nodejs/hangover.js | 57 +++++++++++++++++++++++++++++++++++++ nodejs/smack_my_bitch_up.js | 56 ++++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+) create mode 100755 nodejs/hangover.js create mode 100755 nodejs/smack_my_bitch_up.js diff --git a/nodejs/hangover.js b/nodejs/hangover.js new file mode 100755 index 00000000..2088af3d --- /dev/null +++ b/nodejs/hangover.js @@ -0,0 +1,57 @@ +#!/usr/bin/env node + +/* Before running: + npm install twilio +*/ + +var exec = require('child_process').exec; + +var me = 'my_username'; + +exec("who -q", function(error, stdout, stderr) { + + // Exit if sessions with my username are found + if(stdout.indexOf(me) > -1) + process.exit(1); + + var TWILIO_ACCOUNT_SID = process.env['TWILIO_ACCOUNT_SID']; + var TWILIO_AUTH_TOKEN = process.env['TWILIO_AUTH_TOKEN']; + + // Phone numbers + var MY_NUMBER = '+xxx'; + var BOSS_NUMBER = '+xxx'; + + // Excuses + var excuses = [ + 'Locked out', + 'Pipes broke', + 'Food poisoning', + 'Not feeling well' + ]; + + // Generate BS message + var excuse = excuses[Math.floor(Math.random() * excuses.length)]; + var textMessage = 'Gonna work from home. ' + excuse; + + var client = require('twilio')(TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN); + + // Shoot text + client.messages.create({ + body: textMessage, + to: BOSS_NUMBER, + from: MY_NUMBER + }, function(error, message) { + if(error) + console.log('Failed to send SMS: ' + error.message); + else { + var currentdate = new Date(); + + console.log('Message sent at: '+ (currentdate.getMonth() + 1) + '/' + + currentdate.getDate() + '/' + + currentdate.getFullYear() + ' ' + + currentdate.getHours() + ':' + + currentdate.getMinutes() + ':' + + currentdate.getSeconds() + '| Excuse: ' + excuse); + } + }); +}); diff --git a/nodejs/smack_my_bitch_up.js b/nodejs/smack_my_bitch_up.js new file mode 100755 index 00000000..ebc47ead --- /dev/null +++ b/nodejs/smack_my_bitch_up.js @@ -0,0 +1,56 @@ +#!/usr/bin/env node + +/* Before running: + npm install twilio +*/ + +var exec = require('child_process').exec; + +var me = 'my_username'; + +exec("who -q", function(error, stdout, stderr) { + + // Exit if no sessions with my username are found + if(stdout.indexOf(me) == -1) + process.exit(1); + + var TWILIO_ACCOUNT_SID = process.env['TWILIO_ACCOUNT_SID']; + var TWILIO_AUTH_TOKEN = process.env['TWILIO_AUTH_TOKEN']; + + // Phone numbers + var MY_NUMBER = '+xxx'; + var HER_NUMBER = '+xxx'; + + // Reasons + var reasons = [ + 'Working hard', + 'Gotta ship this feature', + 'Someone fucked the system again' + ]; + + // Generate BS message + var reason = reasons[Math.floor(Math.random() * reasons.length)]; + var textMessage = 'Late at work. ' + reason; + + var client = require('twilio')(TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN); + + // Shoot text + client.messages.create({ + body: textMessage, + to: HER_NUMBER, + from: MY_NUMBER + }, function(error, message) { + if(error) + console.log('Failed to send SMS: ' + error.message); + else { + var currentdate = new Date(); + + console.log('Message sent at: '+ (currentdate.getMonth() + 1) + '/' + + currentdate.getDate() + '/' + + currentdate.getFullYear() + ' ' + + currentdate.getHours() + ':' + + currentdate.getMinutes() + ':' + + currentdate.getSeconds() + '| Excuse: ' + reason); + } + }); +}); From 8d18571e99dd28327728d6cd0b50271517ab35f8 Mon Sep 17 00:00:00 2001 From: RandomlyKnighted Date: Tue, 1 Dec 2015 23:08:12 -0600 Subject: [PATCH 32/63] Added powershell files --- powershell/fucking_coffee.psm1 | 62 ++++++++++++++++++++++++++++++++ powershell/hangover.psm1 | 64 ++++++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 powershell/fucking_coffee.psm1 create mode 100644 powershell/hangover.psm1 diff --git a/powershell/fucking_coffee.psm1 b/powershell/fucking_coffee.psm1 new file mode 100644 index 00000000..55b12898 --- /dev/null +++ b/powershell/fucking_coffee.psm1 @@ -0,0 +1,62 @@ +<# +.SYNOPSIS + Simple script to connect to a coffee part using TelNet then issue specific commands that + brew and pourt a cup of coffee for the user. +.DESCRIPTION + This script was converted using the ruby version of the fucking_coffee script. In this script, + I left the use of environment variables since its only use was to determine if the user was + still logged in to the system. Per issue #42 (https://github.com/NARKOZ/hacker-scripts/issues/42) + I left the password string hard coded until a decision is made by NARKOZ, the project owner, as + to how the information should be stored. +.OUTPUT + None +.NOTES + Author: Tyler Hughes + Twitter: @thughesIT + Blog: http://tylerhughes.info/ + + Changelog: + 1.0 Initial Release +#> + +Function Fucking-Coffee +{ + # Exit early if no sessions with my username are found + if ($env:Username.Count > 0) { + return + } + + $coffee_machine_ip = '10.10.42.42' + $password = '1234' + + Start-Sleep -s 17 + + $socket = New-Object System.Net.Sockets.TcpClient($coffee_machine_ip) + if ($socket) { + $stream = $connection.GetStream() + $Writer = New-Object System.IO.StreamWriter($Stream) + $Buffer = New-Object System.Byte[] 1024 + $Encoding = New-Object System.Text.AsciiEncoding + + # Start issuing the commands + Send-TelNetCommands($Writer, $password, 1) + Send-TelNetCommands($Writer, "sys brew", 24) + Send-TelNetCommands($Writer, "sys pour", 4) + + $socket.Close() + } +} + +Function Send-TelNetCommands +{ + Param ( + [Parameter(ValueFromPipeline=$false)] + [System.IO.StreamWriter]$writer, + [String]$command, + [int]$WaitTime + ) + + $writer.WriteLine($command) + $writer.Flush() + Start-Sleep -Milliseconds $WaitTime +} \ No newline at end of file diff --git a/powershell/hangover.psm1 b/powershell/hangover.psm1 new file mode 100644 index 00000000..fabb13fd --- /dev/null +++ b/powershell/hangover.psm1 @@ -0,0 +1,64 @@ +<# +.SYNOPSIS + Simple script to SMS a supervisor informing them you will be working from home + on the day this script is used. +.DESCRIPTION + This script was converted using the ruby version of the hangover script. However, the ruby + version used environment variables to hold the user's account information. Due to issue #42 + (https://github.com/NARKOZ/hacker-scripts/issues/42) I opted to hard code the strings at + this time until a decision is made by NARKOZ, the project owner, as the how the information + should be stored. + + This script also uses Twilio to send the SMS messages. The from number MUST be a valid Twilio + phone number. The to number can be any outgoing number. +.OUTPUT + This script will output an error message to the PowerShell window if it fails + to send the message. +.NOTES + Author: Tyler Hughes + Twitter: @thughesIT + Blog: http://tylerhughes.info/ + + Changelog: + 1.0 Initial Release +#> +Function Hangover +{ + # Phone numbers (Must include country code and area code) + $from = '+XXXXXXXXXXX' + $to = '+XXXXXXXXXXX' + + # Twilio API Information + $twilio_base_url = 'https://api.twilio.com/2010-04-01' + $twilio_account_sid = 'XXXXXXXXXXXXXXXXXXX' + $twilio_auth_token = 'XXXXXXXXXXXXXXXXXX' + + $password = ConvertTo-SecureString -AsPlainText $twilio_auth_token -Force + $credentials = New-Object System.Management.Automation.PSCredential($twilio_account_sid, $password) + + # Get the message to send + $excuses = + 'Locked out', + 'Pipes broke', + 'Food poisoning', + 'Not feeling well' + + $excuse = $excuses | Get-Random + $message = "$excuse. Going to work from home today." + $body = @{ + From = $from; + To = $to; + Body = $message; + } + + # Send the message and log any errors + $uri = "$twilio_base_url/Accounts/" + $credentials.UserName + "/SMS/Messages" + + try { + $response = Invoke-RestMethod -Method Post -Uri $uri -Body $body -Credential $credentials + } + catch { + $time = Get-Date -format u + Write-Host $time " - Failed to send message: " $message + } +} \ No newline at end of file From 7bf95ed6e7dfb4c531c5f2655bef93ae20af7530 Mon Sep 17 00:00:00 2001 From: Akshay Kashyap Date: Wed, 2 Dec 2015 00:14:54 -0500 Subject: [PATCH 33/63] NodeJS for kumar_asshole --- nodejs/kumar_asshole.js | 113 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100755 nodejs/kumar_asshole.js diff --git a/nodejs/kumar_asshole.js b/nodejs/kumar_asshole.js new file mode 100755 index 00000000..0276f295 --- /dev/null +++ b/nodejs/kumar_asshole.js @@ -0,0 +1,113 @@ +#!/usr/bin/env node + +/* Before running: + npm install nodemailer + npm install imap + +I realize this is long. IMAP can only fetch emails and nodemailer can only +send. Could try implementing with Gmail Node API later. +*/ + +var GMAIL_USERNAME = process.env['GMAIL_USERNAME']; +var GMAIL_PASSWORD = process.env['GMAIL_PASSWORD']; + +var KUMAR_EMAIL = 'kumar.asshole@example.com'; +var EMAIL = 'No worries mate, be careful next time'; + +// Scan for unread email from Kumar +var Imap = require('imap'); +var imap = new Imap({ + user: GMAIL_USERNAME, + password: GMAIL_PASSWORD, + host: 'imap.gmail.com', + port: 993, + tls: true, + tlsOptions: { rejectUnauthorized: false } +}); + +function openInbox(cb) { + imap.openBox('INBOX', false, cb); +} + +imap.once('ready', function() { + openInbox(function(err, box) { + if (err) + process.exit(1); + + imap.search(['UNSEEN', ['FROM', KUMAR_EMAIL]], + function(err, results) { + + if (err) + process.exit(1); + + // RegEx search for keywords; ignore case + var kumarPattern = new RegExp(/sorry|help|wrong/i); + + // IMAP dumps all headers, so need to parse and get email body + var MailParser = require("mailparser").MailParser; + + var f = imap.fetch(results, {bodies: ''}); + f.on('message', function(msg, seqno) { + msg.on('body', function(stream, info) { + var kumarEmail = ""; + + stream.on('data', function(chunk) { + kumarEmail += chunk.toString('utf8'); + }); + + stream.once('end', function() { + var mailparser = new MailParser(); + mailparser.on("end", function(mail_object){ + + // If the RegEx matches + if(mail_object.text.match(kumarPattern)) { + // Shoot email to Kumar! + var nodemailer = require('nodemailer'); + + // create reusable transporter object using SMTP transport + var transporter = nodemailer.createTransport({ + service: 'Gmail', + auth: { + user: GMAIL_USERNAME, + pass: GMAIL_PASSWORD + } + }); + + // setup e-mail data + var mailOptions = { + from: GMAIL_USERNAME, + to: KUMAR_EMAIL, + subject: 'Database Fixes', + text: EMAIL + }; + + // send mail with defined transport object + transporter.sendMail(mailOptions, function(error, info) { + if(error) + process.exit(1) + }); + } + }); + + mailparser.write(kumarEmail); + mailparser.end(); + }); + }); + + msg.once('end', function() { + // Fetched all unread from kumar + }); + }); + + f.once('error', function(err) { + process.exit(1); + }); + + f.once('end', function() { + imap.end(); + }); + }); + }); +}); + +imap.connect(); From ef1822402c547c8b4e2d8a31e24c82d4967f78b2 Mon Sep 17 00:00:00 2001 From: Akshay Kashyap Date: Wed, 2 Dec 2015 12:48:17 -0500 Subject: [PATCH 34/63] NodeJS for fucking_coffee to trigger using Yo. Fixed server messages. NodeJS for fucking_coffee to trigger using Yo. --- nodejs/fucking_coffee_yo_server.js | 83 ++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100755 nodejs/fucking_coffee_yo_server.js diff --git a/nodejs/fucking_coffee_yo_server.js b/nodejs/fucking_coffee_yo_server.js new file mode 100755 index 00000000..28637c2d --- /dev/null +++ b/nodejs/fucking_coffee_yo_server.js @@ -0,0 +1,83 @@ +#!/usr/bin/env node + +/* Before running: + Setup Yo Callback URL and Yo username for coffee machine: + http://docs.justyo.co/docs/receiving-a-yo-with-the-api +*/ + +var exec = require('child_process').exec; +var telnet = require('telnet-client'); + +var ME = 'my_username'; +var AUTHORIZED_YO_NAMES = [ME]; +var COFFEE_MACHINE_YO_NAME = 'coffeemachine'; + +// These should be same as what you set up in the Yo API +var CALLBACK_URL = 'http://xxx.com/'; +var CALLBACK_ENDPOINT = '/coffeemachine'; + +var PORT = '3000'; + +exec("who -q", function(error, stdout, stderr) { + + var express = require('express'); + var coffeeApp = express(); + + // Exit if no sessions with my username are found + if(stdout.indexOf(ME) == -1) + process.exit(1); + + // Got a Yo! + coffeeApp.get(CALLBACK_ENDPOINT, function (req, res) { + + if(req.query.username === undefined) { + // Not a Yo, don't make coffee. + res.sendStatus(401); + } + else if(AUTHORIZED_YO_NAMES.indexOf(req.query.username) == -1) { + // If authorized users didn't Yo, don't make coffee. + res.sendStatus(401); + + console.log(req.query.username + ' YO\'d.') + } + else { + res.sendStatus(200); + + var coffee_machine_ip = 'xxx.xxx.xxx.xxx'; + var password = 'xxxx'; + var con = new telnet(); + + con.on('ready', function(prompt) { + con.exec('Password: ' + password, function(error, res) { + + // Brew Coffee! + con.exec('sys brew', function(error, res) { + + // Wait for 24s + setTimeout(function() { + + // Pour Coffee! + con.exec('sys pour', function(error, res) { + con.end(); + }); + }, 24000); + }); + }); + }); + + con.connect({host: coffee_machine_ip}); + } + }); + + // Not Callback endpoint + coffeeApp.get('/*', function (req, res) { + res.sendStatus(404); + }); + + var coffeeServer = coffeeApp.listen(PORT, CALLBACK_URL, function() { + console.log('Coffee Server listening at %s:%s', + CALLBACK_URL, PORT); + console.log('\nYo Callback URL: %s:%s/%s', + CALLBACK_URL, PORT, CALLBACK_ENDPOINT); + }); +}); From 6ec31b425eb285f4145e96c18a88a91ae956b90c Mon Sep 17 00:00:00 2001 From: Ahmad Samiei Date: Thu, 3 Dec 2015 18:51:21 +0800 Subject: [PATCH 35/63] no need to load .env file for this script USER already exist by default in environment .env file only used to store gmail and twilio credentials --- php/fucking_coffee.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/php/fucking_coffee.php b/php/fucking_coffee.php index 071d1d71..074e22fe 100644 --- a/php/fucking_coffee.php +++ b/php/fucking_coffee.php @@ -3,9 +3,6 @@ require 'vendor/autoload.php'; -$dotenv = new Dotenv\Dotenv(__DIR__); -$dotenv->load(); - use Bestnetwork\Telnet\TelnetClient; (strpos(exec('who'), getenv('USER')) !== false) or exit('no session'); From 1d54a8eb6f34efb8c67a7065fdebfd63889dfc69 Mon Sep 17 00:00:00 2001 From: Ahmad Samiei Date: Fri, 4 Dec 2015 10:36:31 +0800 Subject: [PATCH 36/63] add hangover php port --- php/composer.json | 3 ++- php/hangover.php | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 php/hangover.php diff --git a/php/composer.json b/php/composer.json index 376b4941..e0f86d86 100644 --- a/php/composer.json +++ b/php/composer.json @@ -1,6 +1,7 @@ { "require": { "bestnetwork/telnet": "^1.0", - "vlucas/phpdotenv": "^2.0" + "vlucas/phpdotenv": "^2.0", + "twilio/sdk": "^4.6" } } diff --git a/php/hangover.php b/php/hangover.php new file mode 100644 index 00000000..a660c4c0 --- /dev/null +++ b/php/hangover.php @@ -0,0 +1,21 @@ +#!/usr/bin/env php +load(); +(strpos(exec('who'), getenv('USER')) === false) or exit('session found'); + +$my_number = '+xxx'; +$number_of_boss = '+xxx'; +$excuse = ['Locked out', 'Pipes broke', 'Food poisoning', 'Not feeling well']; +$excuse = $excuse[array_rand($excuse)]; + +$twilio = new Services_Twilio(getenv('TWILIO_ACCOUNT_SID'), getenv('TWILIO_AUTH_TOKEN')); +$twilio->account->messages->sendMessage( + $my_number, + $number_of_boss, + "Gonna work from home. {$excuse}" +); + +echo "Message sent at: #".date('Y-m-d')." | Excuse: {$excuse}"; From 7f9d6b1c4d076380aa2665d6b0db9d69c2da6ae9 Mon Sep 17 00:00:00 2001 From: Chris Topaloudis Date: Fri, 4 Dec 2015 15:48:45 +0100 Subject: [PATCH 37/63] Indentation fix --- python/smack_my_bitch_up.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/smack_my_bitch_up.py b/python/smack_my_bitch_up.py index 02c7e051..17bd3216 100755 --- a/python/smack_my_bitch_up.py +++ b/python/smack_my_bitch_up.py @@ -17,7 +17,7 @@ TWILIO_AUTH_TOKEN = os.environ.get('TWILIO_AUTH_TOKEN') # Phone numbers -my_number = '+xxx' +my_number = '+xxx' her_number = '+xxx' reasons = [ From a78bc2dbb5e261519c23bd39b461c7e2ecff05b4 Mon Sep 17 00:00:00 2001 From: Mohammad Nasirifar Date: Fri, 4 Dec 2015 22:22:51 +0330 Subject: [PATCH 38/63] Added java directory + fucking_coffee.java --- java/fucking_coffee.java | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 java/fucking_coffee.java diff --git a/java/fucking_coffee.java b/java/fucking_coffee.java new file mode 100644 index 00000000..569314ac --- /dev/null +++ b/java/fucking_coffee.java @@ -0,0 +1,34 @@ +import java.net.*; +import java.io.*; + +public class fucking_coffee{ + + private static final String MY_USERNAME = "my_username"; + private static final String PASSWORD_PROMPT = "Password: "; + private static final String PASSWORD = "1234"; + private static final String COFFEE_MACHINE_IP = "10.10.42.42"; + private static int DELAY_BEFORE_BREW = 17; + private static int DELAY = 24; + + public static void main(String[] args)throws Exception{ + for(int i = 1; i< args.length ; i++){ + if(!args[i].contains(MY_USERNAME)){ + return; + } + } + Socket telnet = new Socket(COFFEE_MACHINE_IP, 23); + PrintWriter out = new PrintWriter(telnet.getOutputStream(), true); + BufferedReader in = new BufferedReader(new InputStreamReader(telnet.getInputStream())); + Thread.sleep(DELAY_BEFORE_BREW*1000); + if(in.readLine() != PASSWORD_PROMPT){ + return ; + } + out.println(PASSWORD); + out.println("sys brew"); + Thread.sleep(DELAY*1000); + out.println("sys pour"); + out.close(); + in.close(); + telnet.close(); + } +} From 7d11758390001c82b19e792f7d81471903fcb26b Mon Sep 17 00:00:00 2001 From: Amir Karimi Date: Mon, 7 Dec 2015 13:31:01 +0330 Subject: [PATCH 39/63] Implement Scala version of the fucking-coffee script using Ammonite shell --- scala/fucking-coffee.scala | 43 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 scala/fucking-coffee.scala diff --git a/scala/fucking-coffee.scala b/scala/fucking-coffee.scala new file mode 100644 index 00000000..20432bc4 --- /dev/null +++ b/scala/fucking-coffee.scala @@ -0,0 +1,43 @@ +/******************************************* + * + * Get and run Ammonite (http://lihaoyi.github.io/Ammonite/#Ammonite-Shell): + * $ mkdir ~/.ammonite; curl -L -o ~/.ammonite/predef.scala http://git.io/vR04f + * $ curl -L -o amm http://git.io/vR08A; chmod +x amm; ./amm + * + * Run script: + * @ load.exec("fucking-coffee.scala") + * + *******************************************/ + +import java.net._ +import java.io._ +import ammonite.ops._ + +val coffeeMachineIP = "10.10.42.42" +val password = "1234" +val passwordPrompt = "Password: " +val delayBeforeBrew = 17 +val delay = 24 + +if ((%%who "-q").out.string.contains(sys.props("user.name"))) { + + val telnet = new Socket(coffeeMachineIP, 23) + val out = new PrintWriter(telnet.getOutputStream, true) + val in = new BufferedReader(new InputStreamReader(telnet.getInputStream)) + + Thread.sleep(delayBeforeBrew * 1000); + + if(in.readLine == passwordPrompt){ + out.println(password) + + out.println("sys brew") + Thread.sleep(delay * 1000) + out.println("sys pour") + + } + + out.close() + in.close() + telnet.close() + +} \ No newline at end of file From 7669e87e0a707a4bb9a2d4828cbfbf5f3f24f119 Mon Sep 17 00:00:00 2001 From: gandrianakis Date: Mon, 7 Dec 2015 13:11:33 +0200 Subject: [PATCH 40/63] Added a groovy version of fucking_coffee --- groovy/fucking_coffee.groovy | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 groovy/fucking_coffee.groovy diff --git a/groovy/fucking_coffee.groovy b/groovy/fucking_coffee.groovy new file mode 100644 index 00000000..7411f3cc --- /dev/null +++ b/groovy/fucking_coffee.groovy @@ -0,0 +1,26 @@ +@Grab(group='org.hidetake', module='groovy-ssh', version='1.1.8') +@GrabExclude('org.codehaus.groovy:groovy-all') +import org.hidetake.groovy.ssh.Ssh + +final def ssh = Ssh.newService() + +final def HOST = '10.10.42.42' +final def USER = 'my_username' +final def PASSWORD = '1234' +final def DELAY = 24 + +ssh.remotes { + webServer { + host = HOST + user = USER + password = PASSWORD + } +} + +ssh.run { + session(ssh.remotes.webServer) { + execute 'sys brew' + execute "sleep ${DELAY}s" + execute 'sys pour' + } +} From 895b9228d3d2f7bf7ec7b950e8d03f446bbbf043 Mon Sep 17 00:00:00 2001 From: Amir Karimi Date: Mon, 7 Dec 2015 14:54:43 +0330 Subject: [PATCH 41/63] Run script from bash --- scala/fucking-coffee.scala | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/scala/fucking-coffee.scala b/scala/fucking-coffee.scala index 20432bc4..b40d0834 100644 --- a/scala/fucking-coffee.scala +++ b/scala/fucking-coffee.scala @@ -1,17 +1,18 @@ /******************************************* * - * Get and run Ammonite (http://lihaoyi.github.io/Ammonite/#Ammonite-Shell): + * Get Ammonite (http://lihaoyi.github.io/Ammonite/#Ammonite-Shell): * $ mkdir ~/.ammonite; curl -L -o ~/.ammonite/predef.scala http://git.io/vR04f - * $ curl -L -o amm http://git.io/vR08A; chmod +x amm; ./amm + * $ curl -L -o amm http://git.io/vR08A; chmod +x amm * - * Run script: - * @ load.exec("fucking-coffee.scala") + * Run script + * $ ./amm fucking-coffee.scala * *******************************************/ import java.net._ import java.io._ import ammonite.ops._ +import ammonite.ops.ImplicitWd._ val coffeeMachineIP = "10.10.42.42" val password = "1234" @@ -25,6 +26,7 @@ if ((%%who "-q").out.string.contains(sys.props("user.name"))) { val out = new PrintWriter(telnet.getOutputStream, true) val in = new BufferedReader(new InputStreamReader(telnet.getInputStream)) + println(s"Wait for $delayBeforeBrew seconds") Thread.sleep(delayBeforeBrew * 1000); if(in.readLine == passwordPrompt){ From 48f2da4d084b452809b402afc0805502f8321b49 Mon Sep 17 00:00:00 2001 From: Yoann Duc Date: Tue, 8 Dec 2015 15:07:35 +0100 Subject: [PATCH 42/63] Update smack_my_bitch_up.go Line 34, added %s to string output --- go/smack_my_bitch_up.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/smack_my_bitch_up.go b/go/smack_my_bitch_up.go index 66f7311f..7e7fb7a3 100755 --- a/go/smack_my_bitch_up.go +++ b/go/smack_my_bitch_up.go @@ -31,7 +31,7 @@ func main(){ response,err := exec.Command("curl","-fSs","-u",TWILIO_ACCOUNT_SID + ":" + TWILIO_AUTH_TOKEN, "-d", "From=" + MY_NUMBER, "-d", "To=" + HER_NUMBER, "-d" , "Body=" + message, "https://api.twilio.com/2010-04-01/Accounts/" + TWILIO_ACCOUNT_SID + "/Messages").Output() if(err != nil){ - fmt.Printf("Failed to send SMS: ",err) + fmt.Printf("Failed to send SMS: %s",err) return } From 01f35717c7b3e3c3ff47e206b3420609c1c41270 Mon Sep 17 00:00:00 2001 From: Eli B Date: Tue, 8 Dec 2015 21:02:43 -0600 Subject: [PATCH 43/63] fix never detecting no password prompt --- java/fucking_coffee.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/fucking_coffee.java b/java/fucking_coffee.java index 569314ac..f6063119 100644 --- a/java/fucking_coffee.java +++ b/java/fucking_coffee.java @@ -20,7 +20,7 @@ public static void main(String[] args)throws Exception{ PrintWriter out = new PrintWriter(telnet.getOutputStream(), true); BufferedReader in = new BufferedReader(new InputStreamReader(telnet.getInputStream())); Thread.sleep(DELAY_BEFORE_BREW*1000); - if(in.readLine() != PASSWORD_PROMPT){ + if(!in.readLine().equals(PASSWORD_PROMPT)){ return ; } out.println(PASSWORD); From d33d1f55bd91af45dab869310d0af514f9738029 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 10 Dec 2015 08:31:16 -0500 Subject: [PATCH 44/63] Created "smack_my_bitch_up" in php --- php/smack_my_bitch_up.php | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 php/smack_my_bitch_up.php diff --git a/php/smack_my_bitch_up.php b/php/smack_my_bitch_up.php new file mode 100644 index 00000000..f1fc68fb --- /dev/null +++ b/php/smack_my_bitch_up.php @@ -0,0 +1,32 @@ +#!/usr/bin/env php +load(); + +(strpos(exec('who'), getenv('USER')) !== false) or exit('no session'); + +// Phone numbers +$my_number = '+xxx'; +$her_number = '+xxx'; + +$reasons = [ + 'Working hard', + 'Gotta ship this feature', + 'Someone fucked up the system again' +]; + +$rand = rand(0,count($reasons)-1); +$random_reason = $reasons[$rand]; + +$message = 'Late at work. '.$random_reason; + +// Send a text message +$twilio = new Services_Twilio(getenv('TWILIO_ACCOUNT_SID'), getenv('TWILIO_AUTH_TOKEN')); +$twilio->account->messages->sendMessage( + $my_number, + $her_number, + $message +); + +echo 'Message sent at: #'.date('Y-m-d').' | Reason: '.$random_reason; From 3eeb95f0eada2906dd33918e7eb5769f8c404260 Mon Sep 17 00:00:00 2001 From: Luis Moneda Date: Tue, 29 Dec 2015 18:05:30 -0200 Subject: [PATCH 45/63] Update kumar_asshole.py prefetch=True prevents getting None for msg.body --- python/kumar_asshole.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/kumar_asshole.py b/python/kumar_asshole.py index 36f5f67a..6e95d7df 100755 --- a/python/kumar_asshole.py +++ b/python/kumar_asshole.py @@ -12,7 +12,7 @@ if not g.logged_in: sys.exit() -msgs = g.inbox().mail(sender="kumar.a@example.com", unread=True) +msgs = g.inbox().mail(sender="kumar.a@example.com", unread=True, prefetch=True) pattern = re.compile("\bsorry\b | \bhelp\b | \bwrong\b ", flags=re.I) From 66d694ce87cffa648399740668227f5202996ec4 Mon Sep 17 00:00:00 2001 From: matthew-z Date: Fri, 22 Jan 2016 05:11:13 +0900 Subject: [PATCH 46/63] added hangout.R, improved smack-my-bitch-up.R --- R/hangover.R | 35 +++++++++++++++++++++++++++++++++++ R/smack_my_bitch_up.R | 2 +- 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 R/hangover.R diff --git a/R/hangover.R b/R/hangover.R new file mode 100644 index 00000000..44123c01 --- /dev/null +++ b/R/hangover.R @@ -0,0 +1,35 @@ +library(httr) + +today = Sys.Date() + +# skip weekends +if( weekdays(today) %in% c('Saturday','Sunday') ){ + quit() + } + +# exit if no sessions with my username are found +output = system("who", intern = TRUE) +if( !( grep('^my_user_name', output) ) ){ + quit() + } + +# returns 'None' if the key doesn't exist +TWILIO_ACCOUNT_SID = Sys.getenv('TWILIO_ACCOUNT_SID') +TWILIO_AUTH_TOKEN = Sys.getenv('TWILIO_AUTH_TOKEN') + +# Phone numbers +my_number = '+xxx' +number_of_boss= '+xxx' + +excuse = c( + 'Locked out', + 'Pipes broke', + 'Food poisoning', + 'Not feeling well' + ) + +POST(paste("https://api.twilio.com/2010-04-01/Accounts/",TWILIO_ACCOUNT_SID,"/Messages.json",sep=""), + body = list(From=my_number,To=number_of_boss,Body=paste("Gonna work from home. ", sample(excuse,1))), + authenticate(TWILIO_ACCOUNT_SID,TWILIO_AUTH_TOKEN) ) + +print( paste("Message sent at",Sys.time()) ) diff --git a/R/smack_my_bitch_up.R b/R/smack_my_bitch_up.R index 7257f88e..28fd2868 100644 --- a/R/smack_my_bitch_up.R +++ b/R/smack_my_bitch_up.R @@ -28,7 +28,7 @@ reasons = c( ) POST(paste("https://api.twilio.com/2010-04-01/Accounts/",TWILIO_ACCOUNT_SID,"/Messages.json",sep=""), - body = list(From=my_number,To=her_number,Body=sample(reasons,1) ), + body = list(From=my_number,To=her_number,Body=paste("Late at work. ", sample(reasons,1))), authenticate(TWILIO_ACCOUNT_SID,TWILIO_AUTH_TOKEN) ) print( paste("Message sent at",Sys.time()) ) From 0937bac54420dca63648b7697e5c02cbdb77c9cb Mon Sep 17 00:00:00 2001 From: syedautherabbas Date: Wed, 27 Jan 2016 23:25:56 +0530 Subject: [PATCH 47/63] Added Kumar_Asshole.java --- java/Kumar_asshole.java | 95 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 java/Kumar_asshole.java diff --git a/java/Kumar_asshole.java b/java/Kumar_asshole.java new file mode 100644 index 00000000..cd94ce15 --- /dev/null +++ b/java/Kumar_asshole.java @@ -0,0 +1,95 @@ + +import java.io.File; +import java.io.FileInputStream; +import java.util.*; +import java.util.regex.*; + +import javax.mail.*; +import javax.mail.internet.*; +import javax.mail.search.FlagTerm; +//Dependencies- Java mail API + +public class Kumar_Asshole { + + public static void main(String[] args) { + Kumar_Asshole gmail = new Kumar_Asshole(); + gmail.read(); + } + + public void read() { + Properties props = new Properties(); + + + //modify below properties to your details + String host = "smtp.gmail.com"; + String username = "yourmailaddress@example.com goes here"; + String password = "your password goes here "; + String Kumar_mail = "the mail address to be replied to !"; + + try { + + Session session = Session.getDefaultInstance(props, null); + + Store store = session.getStore("imaps"); + store.connect(host, username, password); + + Folder inbox = store.getFolder("inbox"); + inbox.open(Folder.READ_ONLY); + + Message messages[] = inbox.search(new FlagTerm(new Flags(Flags.Flag.SEEN), false)); + + for (int i = 0; i < messages.length; i++) { + + if (messages[i].getFrom()[0].toString().contains(Kumar_mail)) { + + String bodytext = null; + Object content = messages[i].getContent(); + if (content instanceof String) { + bodytext = (String) content; + + } else if (content instanceof Multipart) { + + Multipart mp = (Multipart) content; + + BodyPart bp = mp.getBodyPart(mp.getCount() - 1); + bodytext = (String) bp.getContent(); + + } + + Pattern pattern = Pattern.compile("sorry|help|wrong", Pattern.CASE_INSENSITIVE); + Matcher matcher = pattern.matcher(bodytext); + // check all occurance + + if (matcher.find()) { + + Properties props1 = new Properties(); + Address[] tomail; + + MimeMessage msg = new MimeMessage(session); + msg.setFrom(new InternetAddress(username)); + tomail = messages[i].getFrom(); + String t1 = tomail[0].toString(); + msg.addRecipient(Message.RecipientType.TO, new InternetAddress(t1)); + msg.setSubject("Database fixes"); + msg.setText("No problem. I've fixed it. \n\n Please be careful next time."); + Transport t = null; + t = session.getTransport("smtps"); + t.connect(host, username, password); + t.sendMessage(msg, msg.getAllRecipients()); + + + } + + + } + } + inbox.close(true); + store.close(); + + }catch(Exception e) + { + + e.printStackTrace(); + } + } +} \ No newline at end of file From 73e27a8975bbe073ad3f45ab0cf146db7f8005d8 Mon Sep 17 00:00:00 2001 From: Shadab Mehdi Date: Wed, 27 Jan 2016 23:58:29 +0530 Subject: [PATCH 48/63] Added SmackMyBitch.java --- java/SmackMyBitch.java | 43 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 java/SmackMyBitch.java diff --git a/java/SmackMyBitch.java b/java/SmackMyBitch.java new file mode 100644 index 00000000..c3011ef6 --- /dev/null +++ b/java/SmackMyBitch.java @@ -0,0 +1,43 @@ +import com.twilio.sdk.TwilioRestClient; +import com.twilio.sdk.TwilioRestException; +import com.twilio.sdk.resource.factory.MessageFactory; +import com.twilio.sdk.resource.instance.Message; +import org.apache.http.NameValuePair; +import org.apache.http.message.BasicNameValuePair; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + + +public class SmackMyBitch { + + public static final String ACCOUNT_SID = System.getenv("TWILIO_ACCOUNT_SID"); + public static final String AUTH_TOKEN = System.getenv("TWILIO_AUTH_TOKEN"); + + public static final String YOUR_NUMBER = "1231231231"; + public static final String HER_NUMBER = "3213213213"; + + public static void main(String[] args) throws TwilioRestException { + + TwilioRestClient client = new TwilioRestClient(ACCOUNT_SID, AUTH_TOKEN); + + String[] randomMessages = { + "Working hard", + "Gotta ship this feature", + "Someone fucked the system again", + }; + + int randomIndex = new Random().nextInt(randomMessages.length); + String finalMessage = (randomMessages[randomIndex]); + + List params = new ArrayList(); + params.add(new BasicNameValuePair("Body", "Late at work. " + finalMessage)); + params.add(new BasicNameValuePair("From", YOUR_NUMBER)); + params.add(new BasicNameValuePair("To", HER_NUMBER)); + + MessageFactory messageFactory = client.getAccount().getMessageFactory(); + Message message = messageFactory.create(params); + System.out.println(message.getSid()); + } +} \ No newline at end of file From 1c53ad617820df3f43e9cdb0b42360f4473041cd Mon Sep 17 00:00:00 2001 From: Shadab Mehdi Date: Thu, 28 Jan 2016 00:37:59 +0530 Subject: [PATCH 49/63] Added Hangover.java --- java/Hangover.java | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 java/Hangover.java diff --git a/java/Hangover.java b/java/Hangover.java new file mode 100644 index 00000000..50177ef6 --- /dev/null +++ b/java/Hangover.java @@ -0,0 +1,44 @@ +import com.twilio.sdk.TwilioRestClient; +import com.twilio.sdk.TwilioRestException; +import com.twilio.sdk.resource.factory.MessageFactory; +import com.twilio.sdk.resource.instance.Message; +import org.apache.http.NameValuePair; +import org.apache.http.message.BasicNameValuePair; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +public class Hangover { + + public static final String ACCOUNT_SID = System.getenv("TWILIO_ACCOUNT_SID"); + public static final String AUTH_TOKEN = System.getenv("TWILIO_AUTH_TOKEN"); + + public static final String YOUR_NUMBER = "1231231231"; + public static final String BOSS_NUMBER = "3213213213"; + + public static void main(String[] args) throws TwilioRestException { + + TwilioRestClient client = new TwilioRestClient(ACCOUNT_SID, AUTH_TOKEN); + + String[] randomMessages = { + "Locked out", + "Pipes broke", + "Food poisoning", + "Not feeling well" + }; + + int randomIndex = new Random().nextInt(randomMessages.length); + String finalMessage = (randomMessages[randomIndex]); + + List params = new ArrayList(); + params.add(new BasicNameValuePair("Body", "Gonna work from home. " + finalMessage)); + params.add(new BasicNameValuePair("From", YOUR_NUMBER)); + params.add(new BasicNameValuePair("To", BOSS_NUMBER)); + + MessageFactory messageFactory = client.getAccount().getMessageFactory(); + Message message = messageFactory.create(params); + System.out.println(message.getSid()); + } +} + From 01e916f59cf76e1ac4bc9cb9add32df7490a423c Mon Sep 17 00:00:00 2001 From: Nihad Abbasov Date: Mon, 29 Feb 2016 12:57:12 +0400 Subject: [PATCH 50/63] rm extra files --- java/Kumar_asshole.java | 95 ---------------------------------------- java/fucking_coffee.java | 34 -------------- 2 files changed, 129 deletions(-) delete mode 100644 java/Kumar_asshole.java delete mode 100644 java/fucking_coffee.java diff --git a/java/Kumar_asshole.java b/java/Kumar_asshole.java deleted file mode 100644 index cd94ce15..00000000 --- a/java/Kumar_asshole.java +++ /dev/null @@ -1,95 +0,0 @@ - -import java.io.File; -import java.io.FileInputStream; -import java.util.*; -import java.util.regex.*; - -import javax.mail.*; -import javax.mail.internet.*; -import javax.mail.search.FlagTerm; -//Dependencies- Java mail API - -public class Kumar_Asshole { - - public static void main(String[] args) { - Kumar_Asshole gmail = new Kumar_Asshole(); - gmail.read(); - } - - public void read() { - Properties props = new Properties(); - - - //modify below properties to your details - String host = "smtp.gmail.com"; - String username = "yourmailaddress@example.com goes here"; - String password = "your password goes here "; - String Kumar_mail = "the mail address to be replied to !"; - - try { - - Session session = Session.getDefaultInstance(props, null); - - Store store = session.getStore("imaps"); - store.connect(host, username, password); - - Folder inbox = store.getFolder("inbox"); - inbox.open(Folder.READ_ONLY); - - Message messages[] = inbox.search(new FlagTerm(new Flags(Flags.Flag.SEEN), false)); - - for (int i = 0; i < messages.length; i++) { - - if (messages[i].getFrom()[0].toString().contains(Kumar_mail)) { - - String bodytext = null; - Object content = messages[i].getContent(); - if (content instanceof String) { - bodytext = (String) content; - - } else if (content instanceof Multipart) { - - Multipart mp = (Multipart) content; - - BodyPart bp = mp.getBodyPart(mp.getCount() - 1); - bodytext = (String) bp.getContent(); - - } - - Pattern pattern = Pattern.compile("sorry|help|wrong", Pattern.CASE_INSENSITIVE); - Matcher matcher = pattern.matcher(bodytext); - // check all occurance - - if (matcher.find()) { - - Properties props1 = new Properties(); - Address[] tomail; - - MimeMessage msg = new MimeMessage(session); - msg.setFrom(new InternetAddress(username)); - tomail = messages[i].getFrom(); - String t1 = tomail[0].toString(); - msg.addRecipient(Message.RecipientType.TO, new InternetAddress(t1)); - msg.setSubject("Database fixes"); - msg.setText("No problem. I've fixed it. \n\n Please be careful next time."); - Transport t = null; - t = session.getTransport("smtps"); - t.connect(host, username, password); - t.sendMessage(msg, msg.getAllRecipients()); - - - } - - - } - } - inbox.close(true); - store.close(); - - }catch(Exception e) - { - - e.printStackTrace(); - } - } -} \ No newline at end of file diff --git a/java/fucking_coffee.java b/java/fucking_coffee.java deleted file mode 100644 index f6063119..00000000 --- a/java/fucking_coffee.java +++ /dev/null @@ -1,34 +0,0 @@ -import java.net.*; -import java.io.*; - -public class fucking_coffee{ - - private static final String MY_USERNAME = "my_username"; - private static final String PASSWORD_PROMPT = "Password: "; - private static final String PASSWORD = "1234"; - private static final String COFFEE_MACHINE_IP = "10.10.42.42"; - private static int DELAY_BEFORE_BREW = 17; - private static int DELAY = 24; - - public static void main(String[] args)throws Exception{ - for(int i = 1; i< args.length ; i++){ - if(!args[i].contains(MY_USERNAME)){ - return; - } - } - Socket telnet = new Socket(COFFEE_MACHINE_IP, 23); - PrintWriter out = new PrintWriter(telnet.getOutputStream(), true); - BufferedReader in = new BufferedReader(new InputStreamReader(telnet.getInputStream())); - Thread.sleep(DELAY_BEFORE_BREW*1000); - if(!in.readLine().equals(PASSWORD_PROMPT)){ - return ; - } - out.println(PASSWORD); - out.println("sys brew"); - Thread.sleep(DELAY*1000); - out.println("sys pour"); - out.close(); - in.close(); - telnet.close(); - } -} From 7a82ced99fa0827e47cd9cb554acc3f134f65cc1 Mon Sep 17 00:00:00 2001 From: Will Webb Date: Thu, 31 Mar 2016 18:41:37 +0100 Subject: [PATCH 51/63] Update fucking_coffee.psm1 Corrected spelling in synopsis. --- powershell/fucking_coffee.psm1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/powershell/fucking_coffee.psm1 b/powershell/fucking_coffee.psm1 index 55b12898..980eb621 100644 --- a/powershell/fucking_coffee.psm1 +++ b/powershell/fucking_coffee.psm1 @@ -1,7 +1,7 @@ <# .SYNOPSIS Simple script to connect to a coffee part using TelNet then issue specific commands that - brew and pourt a cup of coffee for the user. + brew and pour a cup of coffee for the user. .DESCRIPTION This script was converted using the ruby version of the fucking_coffee script. In this script, I left the use of environment variables since its only use was to determine if the user was @@ -59,4 +59,4 @@ Function Send-TelNetCommands $writer.WriteLine($command) $writer.Flush() Start-Sleep -Milliseconds $WaitTime -} \ No newline at end of file +} From 0347b0ca02130334db78fef7adffcf2b7838c4dd Mon Sep 17 00:00:00 2001 From: Shahjada Date: Sun, 31 Jan 2016 20:16:24 +0600 Subject: [PATCH 52/63] Added Hangover.cs and implementation Added SmackMyBitch.cs and implementation --- CSharp/Hangover.cs | 34 ++++++++++++++++++++++++++++++++++ CSharp/SmackMyBitch.cs | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 CSharp/Hangover.cs create mode 100644 CSharp/SmackMyBitch.cs diff --git a/CSharp/Hangover.cs b/CSharp/Hangover.cs new file mode 100644 index 00000000..fe7a5888 --- /dev/null +++ b/CSharp/Hangover.cs @@ -0,0 +1,34 @@ +namespace Hacker_Scripts +{ + using System; + using Twilio; + using System.Linq; + + class Hangover + { + public static string TWILIO_ACCOUNT_SID = Environment.GetEnvironmentVariable("TWILIO_ACCOUNT_SID"); + public static string AUTH_TOKEN = Environment.GetEnvironmentVariable("TWILIO_AUTH_TOKEN"); + + public static string YOUR_NUMBER = "9879789978"; + public static string BOSS_NUMBER = "3213213233"; + + static void Main(string[] args) + { + var twilio = new TwilioRestClient(TWILIO_ACCOUNT_SID, AUTH_TOKEN); + + string[] randomMessages = { + "Locked out", + "Pipes broke", + "Food poisoning", + "Not feeling well" + }; + + int randomIndex = new Random().Next(randomMessages.Count()); + String messageToSend = (randomMessages[randomIndex]); + + var message = twilio.SendMessage(YOUR_NUMBER, BOSS_NUMBER, messageToSend); + Console.WriteLine(message.Sid); + } + } +} + diff --git a/CSharp/SmackMyBitch.cs b/CSharp/SmackMyBitch.cs new file mode 100644 index 00000000..d5c13fc1 --- /dev/null +++ b/CSharp/SmackMyBitch.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Twilio; + +namespace Hacker_Scripts +{ + class SmackMyBitch + { + public static string TWILIO_ACCOUNT_SID = Environment.GetEnvironmentVariable("TWILIO_ACCOUNT_SID"); + public static string AUTH_TOKEN = Environment.GetEnvironmentVariable("TWILIO_AUTH_TOKEN"); + + public static string YOUR_NUMBER = "9879789978"; + public static string HER_NUMBER = "3213213233"; + + static void Main(string[] args) + { + var twilio = new TwilioRestClient(TWILIO_ACCOUNT_SID, AUTH_TOKEN); + + string[] randomMessages = { + "Working hard", + "Gotta ship this feature", + "Someone fucked the system again" + }; + + int randomIndex = new Random().Next(randomMessages.Count()); + String messageToSend = (randomMessages[randomIndex]); + + var message = twilio.SendMessage(YOUR_NUMBER, HER_NUMBER, messageToSend); + Console.WriteLine(message.Sid); + } + } +} From e06146e10a6c0af2bf177c31d02cb44f60062767 Mon Sep 17 00:00:00 2001 From: PenguWin Date: Sat, 8 Oct 2016 18:16:55 +0200 Subject: [PATCH 53/63] go fmt on smack_my_bitch_up.go --- go/smack_my_bitch_up.go | 71 ++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 36 deletions(-) diff --git a/go/smack_my_bitch_up.go b/go/smack_my_bitch_up.go index 7e7fb7a3..41966881 100755 --- a/go/smack_my_bitch_up.go +++ b/go/smack_my_bitch_up.go @@ -1,39 +1,38 @@ package main -import( - "os/exec" - "fmt" - "strings" - "os" - "math/rand" - "time" - ) - -func main(){ - output1,err := exec.Command("who").Output() - output2 := os.Getenv("USER") - users := string(output1[:]) - current_user := string(output2[:]) - if(!strings.Contains(users,current_user)){ - return - } - - - reasons := []string {"Working hard","Gotta ship this feature","Someone fucked the system again"} - - rand.Seed(time.Now().UTC().UnixNano()) - message := "Late at work. " + reasons[rand.Intn(len(reasons))] - - TWILIO_ACCOUNT_SID := string(os.Getenv("TWILIO_ACCOUNT_SID")) - TWILIO_AUTH_TOKEN := string(os.Getenv("TWILIO_AUTH_TOKEN")) - MY_NUMBER := string(os.Getenv("MY_NUMBER")) - HER_NUMBER := string(os.Getenv("HER_NUMBER")) - - response,err := exec.Command("curl","-fSs","-u",TWILIO_ACCOUNT_SID + ":" + TWILIO_AUTH_TOKEN, "-d", "From=" + MY_NUMBER, "-d", "To=" + HER_NUMBER, "-d" , "Body=" + message, "https://api.twilio.com/2010-04-01/Accounts/" + TWILIO_ACCOUNT_SID + "/Messages").Output() - if(err != nil){ - fmt.Printf("Failed to send SMS: %s",err) - return - } - - fmt.Printf("Message Sent Successfully with response: %s ",response) +import ( + "fmt" + "math/rand" + "os" + "os/exec" + "strings" + "time" +) + +func main() { + output1, err := exec.Command("who").Output() + output2 := os.Getenv("USER") + users := string(output1[:]) + current_user := string(output2[:]) + if !strings.Contains(users, current_user) { + return + } + + reasons := []string{"Working hard", "Gotta ship this feature", "Someone fucked the system again"} + + rand.Seed(time.Now().UTC().UnixNano()) + message := "Late at work. " + reasons[rand.Intn(len(reasons))] + + TWILIO_ACCOUNT_SID := string(os.Getenv("TWILIO_ACCOUNT_SID")) + TWILIO_AUTH_TOKEN := string(os.Getenv("TWILIO_AUTH_TOKEN")) + MY_NUMBER := string(os.Getenv("MY_NUMBER")) + HER_NUMBER := string(os.Getenv("HER_NUMBER")) + + response, err := exec.Command("curl", "-fSs", "-u", TWILIO_ACCOUNT_SID+":"+TWILIO_AUTH_TOKEN, "-d", "From="+MY_NUMBER, "-d", "To="+HER_NUMBER, "-d", "Body="+message, "https://api.twilio.com/2010-04-01/Accounts/"+TWILIO_ACCOUNT_SID+"/Messages").Output() + if err != nil { + fmt.Printf("Failed to send SMS: %s", err) + return + } + + fmt.Printf("Message Sent Successfully with response: %s ", response) } From 166cae8079dd333235036dba5e9cb3a2240bbbd0 Mon Sep 17 00:00:00 2001 From: Sam Adams Date: Tue, 23 Apr 2019 02:16:28 -0700 Subject: [PATCH 54/63] Clojure implementation (#174) * clojure implementation * gf --> boss * newlines --- clojure/coffee.clj | 39 +++++++++++++++++++++++++ clojure/hangover.clj | 28 ++++++++++++++++++ clojure/kumar.clj | 68 ++++++++++++++++++++++++++++++++++++++++++++ clojure/smack.clj | 28 ++++++++++++++++++ 4 files changed, 163 insertions(+) create mode 100644 clojure/coffee.clj create mode 100644 clojure/hangover.clj create mode 100644 clojure/kumar.clj create mode 100644 clojure/smack.clj diff --git a/clojure/coffee.clj b/clojure/coffee.clj new file mode 100644 index 00000000..96d87eb2 --- /dev/null +++ b/clojure/coffee.clj @@ -0,0 +1,39 @@ +(ns hacker-scripts.coffee + (:require [environ.core :refer [env]]) + (:import + (java.net Socket) + (java.io BufferedReader PrintWriter InputStreamReader))) + +(def my-username "my-username") +(def my-password "my-password") + +(def coffee-machine-ip "10.10.42.42") +(def password-prompt "Password: ") +(def connection-port 23) + +(def sec-delay-before-brew 17) +(def sec-delay-before-pour 24) + +(defn logged-in? [] (= (:USER env) my-username)) + +(defn auth [in-stream out-stream] + (if (= (.readLine in-stream) password-prompt) + (.println out-stream my-password) + (throw (RuntimeException. + "Failed to authenticate with coffee machine")))) + +(defn command-brew-pour [out-stream] + (do + (Thread/sleep (* 1000 sec-delay-before-brew)) + (.println out-stream "sys brew") + (Thread/sleep (* 1000 sec-delay-before-pour)) + (.println out-stream "sys pour"))) + +(defn coffee [] + (if (logged-in?) + (with-open [socket (Socket. coffee-machine-ip connection-port) + out-stream (PrintWriter. (.getOutputStream socket) true) + in-stream (BufferedReader. (InputStreamReader. (.getInputStream socket)))] + (do + (auth in-stream out-stream) + (command-brew-pour out-stream))))) diff --git a/clojure/hangover.clj b/clojure/hangover.clj new file mode 100644 index 00000000..7a71372a --- /dev/null +++ b/clojure/hangover.clj @@ -0,0 +1,28 @@ +(ns hacker-scripts.hangover + (:import + (com.twilio Twilio) + (com.twilio.rest.api.v2010.account Message) + (com.twilio.type PhoneNumber))) + +(def acc-sid "my twilio account SID") +(def acc-tkn "my twilio secret token") + +(def my-num (PhoneNumber. "+10001112222")) +(def boss-num (PhoneNumber. "+19998887777")) + +(def reasons ["Receiving delivery" + "Waiting for repairman" + "Nasty cold"]) + +(defn twilio-init [] + (Twilio/init acc-sid acc-tkn)) + +(defn send-sms [to-num from-num message] + (.. Message (creator to-num from-num message) create)) + +(def send-sms-boss (partial send-sms boss-num my-num)) + +(defn hangover [] + (twilio-init) + (let [message (rand-nth reasons)] + (send-sms-boss message))) diff --git a/clojure/kumar.clj b/clojure/kumar.clj new file mode 100644 index 00000000..e406ce95 --- /dev/null +++ b/clojure/kumar.clj @@ -0,0 +1,68 @@ +(ns hacker-scripts.kumar + (:import + (java.util Properties) + (javax.mail Session Authenticator PasswordAuthentication Message$RecipientType Transport Folder Flags Flags$Flag) + (javax.mail.internet MimeMessage InternetAddress) + (javax.mail.search FlagTerm FromTerm AndTerm OrTerm SubjectTerm BodyTerm SearchTerm))) + +(def host "smtp.gmail.com") +(def my-email "my-email@gmail.com") +(def my-password "my-gmail-password") +(def kumar-email "kumar@gmail.com") + +(def seen-flag (Flags. (Flags$Flag/SEEN))) + +(def unread-term (FlagTerm. seen-flag false)) + +(defn get-session [] + (let [authenticator (proxy [Authenticator] [] + (getPasswordAuthentication [] + (PasswordAuthentication. my-email my-password))) + props (Properties.)] + (.put props "mail.smtp.host" "smtp.gmail.com") + (.put props "mail.smtp.port" "587") + (.put props "mail.smtp.auth" "true") + (.put props "mail.smtp.starttls.enable" "true") + (.. Session (getInstance props authenticator)))) + +(defn get-inbox [session] + (let [store (.getStore session "imaps") + inbox (do + (.connect store host my-email my-password) + (.getFolder store "inbox"))] + (.open inbox Folder/READ_WRITE) + inbox)) + +(defn get-no-worries-message [session] + (let [message (MimeMessage. session)] + (.setFrom message (InternetAddress. my-email)) + (.addRecipient message Message$RecipientType/TO (InternetAddress. kumar-email)) + (.setSubject message "Database fixes") + (.setText message "No worries mate, be careful next time") + message)) + +(defn search-term [pattern] + (OrTerm. (into-array SearchTerm [(SubjectTerm. pattern) (BodyTerm. pattern)]))) + +(defn any-of-search-term [& patterns] + (OrTerm. (into-array (map search-term patterns)))) + +(defn from-term [addr] + (FromTerm. (InternetAddress. addr))) + +(defn get-unread-sos-from-kumar [inbox] + (let [flag (AndTerm. (into-array SearchTerm [unread-term + (from-term kumar-email) + (any-of-search-term "help" "sorry" "trouble")]))] + (.search inbox flag))) + +(defn mark-as-read [inbox messages] + (.setFlags inbox messages seen-flag true)) + +(defn kumar-asshole [] + (let [session (get-session) + inbox (get-inbox session) + unread-sos-from-kumar (get-unread-sos-from-kumar inbox)] + (when (seq unread-sos-from-kumar) + (mark-as-read inbox unread-sos-from-kumar) + (Transport/send (get-no-worries-message session))))) diff --git a/clojure/smack.clj b/clojure/smack.clj new file mode 100644 index 00000000..232a0b1e --- /dev/null +++ b/clojure/smack.clj @@ -0,0 +1,28 @@ +(ns hacker-scripts.smack + (:import + (com.twilio Twilio) + (com.twilio.rest.api.v2010.account Message) + (com.twilio.type PhoneNumber))) + +(def acc-sid "my twilio account SID") +(def acc-tkn "my twilio secret token") + +(def my-num (PhoneNumber. "+10001112222")) +(def her-num (PhoneNumber. "+19998887777")) + +(def reasons ["Working hard" + "Gotta ship this feature" + "Someone fucked the system again"]) + +(defn twilio-init [] + (Twilio/init acc-sid acc-tkn)) + +(defn send-sms [to-num from-num message] + (.. Message (creator to-num from-num message) create)) + +(def send-sms-girlfriend (partial send-sms her-num my-num)) + +(defn smack [] + (twilio-init) + (let [message (rand-nth reasons)] + (send-sms-girlfriend message))) From d98c96fbdbc07b7672fa9383a1339bcf18a61a00 Mon Sep 17 00:00:00 2001 From: theapache64 Date: Mon, 29 Apr 2019 18:51:33 +0530 Subject: [PATCH 55/63] =?UTF-8?q?=F0=9F=8C=9F=20Added=20kotlin?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kotlin/FuckingCoffee.kt | 33 +++++++++++++++ kotlin/Hangover.kt | 41 +++++++++++++++++++ kotlin/KumarAsshole.kt | 91 +++++++++++++++++++++++++++++++++++++++++ kotlin/SmackMyBitch.kt | 42 +++++++++++++++++++ 4 files changed, 207 insertions(+) create mode 100644 kotlin/FuckingCoffee.kt create mode 100644 kotlin/Hangover.kt create mode 100644 kotlin/KumarAsshole.kt create mode 100644 kotlin/SmackMyBitch.kt diff --git a/kotlin/FuckingCoffee.kt b/kotlin/FuckingCoffee.kt new file mode 100644 index 00000000..f775ea93 --- /dev/null +++ b/kotlin/FuckingCoffee.kt @@ -0,0 +1,33 @@ +import java.io.BufferedReader +import java.io.InputStreamReader +import java.io.PrintWriter +import java.net.Socket + +private const val MY_USERNAME = "my_username" +private const val PASSWORD_PROMPT = "Password: " +private const val PASSWORD = "1234" +private const val COFFEE_MACHINE_IP = "10.10.42.42" +private const val DELAY_BEFORE_BREW = 17 +private const val DELAY = 24 + +fun main(args: Array) { + for (i in 1 until args.size) { + if (!args[i].contains(MY_USERNAME)) { + return + } + } + val telnet = Socket(COFFEE_MACHINE_IP, 23) + val out = PrintWriter(telnet.getOutputStream(), true) + val reader = BufferedReader(InputStreamReader(telnet.getInputStream())) + Thread.sleep((DELAY_BEFORE_BREW * 1000).toLong()) + if (reader.readLine() != PASSWORD_PROMPT) { + return + } + out.println(PASSWORD) + out.println("sys brew") + Thread.sleep((DELAY * 1000).toLong()) + out.println("sys pour") + out.close() + reader.close() + telnet.close() +} \ No newline at end of file diff --git a/kotlin/Hangover.kt b/kotlin/Hangover.kt new file mode 100644 index 00000000..35f13ef5 --- /dev/null +++ b/kotlin/Hangover.kt @@ -0,0 +1,41 @@ +import com.twilio.sdk.TwilioRestClient +import com.twilio.sdk.TwilioRestException +import com.twilio.sdk.resource.factory.MessageFactory +import com.twilio.sdk.resource.instance.Message +import org.apache.http.NameValuePair +import org.apache.http.message.BasicNameValuePair + +import java.util.ArrayList +import java.util.Random + +private val ACCOUNT_SID = System.getenv("TWILIO_ACCOUNT_SID") +private val AUTH_TOKEN = System.getenv("TWILIO_AUTH_TOKEN") + +private const val YOUR_NUMBER = "1231231231" +private const val BOSS_NUMBER = "3213213213" + +private val randomMessages = arrayOf( + "Locked out", + "Pipes broke", + "Food poisoning", + "Not feeling well" +) + + +fun main() { + + val client = TwilioRestClient(ACCOUNT_SID, AUTH_TOKEN) + + val finalMessage = randomMessages.random() + + val params = ArrayList().apply { + add(BasicNameValuePair("Body", "Gonna work from home. $finalMessage")) + add(BasicNameValuePair("From", YOUR_NUMBER)) + add(BasicNameValuePair("To", BOSS_NUMBER)) + } + + val messageFactory = client.getAccount().getMessageFactory() + val message = messageFactory.create(params) + System.out.println(message.getSid()) +} + diff --git a/kotlin/KumarAsshole.kt b/kotlin/KumarAsshole.kt new file mode 100644 index 00000000..75c23988 --- /dev/null +++ b/kotlin/KumarAsshole.kt @@ -0,0 +1,91 @@ +import java.io.File +import java.io.FileInputStream +import java.util.* +import java.util.regex.* + +import javax.mail.* +import javax.mail.internet.* +import javax.mail.search.FlagTerm + +//modify below properties to your details +private const val host = "smtp.gmail.com" +private const val username = "yourmailaddress@example.com goes here" +private const val password = "your password goes here " +private const val Kumar_mail = "the mail address to be replied to !" + + +//Dependencies- Java mail API +fun main() { + val asshole = KumarAsshole() + asshole.read() +} + +object KumarAsshole { + + fun read() { + val props = Properties() + + try { + + val session = Session.getDefaultInstance(props, null) + + val store = session.getStore("imaps") + store.connect(host, username, password) + + val inbox = store.getFolder("inbox") + inbox.open(Folder.READ_ONLY) + + val messages = inbox.search(FlagTerm(Flags(Flags.Flag.SEEN), false)) + + for (i in messages.indices) { + + if (messages[i].getFrom()[0].toString().contains(Kumar_mail)) { + + var bodytext: String? = null + val content = messages[i].getContent() + if (content is String) { + bodytext = content + + } else if (content is Multipart) { + + val mp = content as Multipart + + val bp = mp.getBodyPart(mp.getCount() - 1) + bodytext = bp.getContent() + + } + + val pattern = Pattern.compile("sorry|help|wrong", Pattern.CASE_INSENSITIVE) + val matcher = pattern.matcher(bodytext!!) + // check all occurance + + if (matcher.find()) { + + val props1 = Properties() + val tomail: Array
+ + val msg = MimeMessage(session) + msg.setFrom(InternetAddress(username)) + tomail = messages[i].getFrom() + val t1 = tomail[0].toString() + msg.addRecipient(Message.RecipientType.TO, InternetAddress(t1)) + msg.setSubject("Database fixes") + msg.setText("No problem. I've fixed it. \n\n Please be careful next time.") + var t: Transport? = null + t = session.getTransport("smtps") + t!!.connect(host, username, password) + t!!.sendMessage(msg, msg.getAllRecipients()) + } + + + } + } + inbox.close(true) + store.close() + + } catch (e: Exception) { + e.printStackTrace() + } + + } +} \ No newline at end of file diff --git a/kotlin/SmackMyBitch.kt b/kotlin/SmackMyBitch.kt new file mode 100644 index 00000000..9a73bb34 --- /dev/null +++ b/kotlin/SmackMyBitch.kt @@ -0,0 +1,42 @@ +import com.twilio.sdk.TwilioRestClient +import com.twilio.sdk.TwilioRestException +import com.twilio.sdk.resource.factory.MessageFactory +import com.twilio.sdk.resource.instance.Message +import org.apache.http.NameValuePair +import org.apache.http.message.BasicNameValuePair + +import java.util.ArrayList +import java.util.Random + +//Pre-requisite apache http and twilio java libraries + +private const val ACCOUNT_SID = System.getenv("TWILIO_ACCOUNT_SID") +private const val AUTH_TOKEN = System.getenv("TWILIO_AUTH_TOKEN") + +private const val YOUR_NUMBER = "1231231231" +private const val HER_NUMBER = "3213213213" + +private val randomMessages = arrayOf( + "Working hard", + "Gotta ship this feature", + "Someone fucked the system again" +) + + +@Throws(TwilioRestException::class) +fun main() { + + val client = TwilioRestClient(ACCOUNT_SID, AUTH_TOKEN) + + val finalMessage = randomMessages.random() + + val params = mutableListOf().apply { + add(BasicNameValuePair("Body", "Late at work. $finalMessage")) + add(BasicNameValuePair("From", YOUR_NUMBER)) + add(BasicNameValuePair("To", HER_NUMBER)) + } + + val messageFactory = client.getAccount().getMessageFactory() + val message = messageFactory.create(params) + System.out.println(message.getSid()) +} \ No newline at end of file From 5c59766b505d26665d2f91faf8065b9faec39c35 Mon Sep 17 00:00:00 2001 From: Kudzai Chasinda Date: Sun, 3 Nov 2019 13:56:51 +0200 Subject: [PATCH 56/63] Fix space issue on python reply (#184) --- python3/kumar_asshole.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python3/kumar_asshole.py b/python3/kumar_asshole.py index c85155b7..a66b255a 100755 --- a/python3/kumar_asshole.py +++ b/python3/kumar_asshole.py @@ -16,7 +16,7 @@ KUMAR_EMAIL = 'kumar.a@example.com' KEYWORDS_REGEX = re.compile(r'sorry|help|wrong', re.IGNORECASE) -REPLY_BODY = "No problem. I've fixed it. \n\n Please be careful next time." +REPLY_BODY = "No problem. I've fixed it. \n\nPlease be careful next time." yagmail.register(GMAIL_USERNAME, GMAIL_PASSWORD) From 4bf5fe9831a865cc3b1dd7b218ef83ba045ab5e1 Mon Sep 17 00:00:00 2001 From: mpetitjean Date: Wed, 8 Jan 2020 14:19:36 +0100 Subject: [PATCH 57/63] Add 17s delay in fucking-coffee, python (#178) --- python/fucking_coffee.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/python/fucking_coffee.py b/python/fucking_coffee.py index c19572f3..a6ea5e94 100755 --- a/python/fucking_coffee.py +++ b/python/fucking_coffee.py @@ -10,6 +10,8 @@ if 'my_username' not in output: sys.exit() +time.sleep(17) + coffee_machine_ip = '10.10.42.42' password = '1234' password_prompt = 'Password: ' From c03021e12848e3a807f46720ec4219753897fcc4 Mon Sep 17 00:00:00 2001 From: Bharath Srinivas Date: Wed, 8 Jan 2020 18:49:57 +0530 Subject: [PATCH 58/63] ported fucking-coffee script to golang (#163) --- go/fucking-coffee.go | 50 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 go/fucking-coffee.go diff --git a/go/fucking-coffee.go b/go/fucking-coffee.go new file mode 100644 index 00000000..23149d83 --- /dev/null +++ b/go/fucking-coffee.go @@ -0,0 +1,50 @@ +package main + +import ( + "fmt" + "log" + "os" + "regexp" + "time" + + "github.com/codeskyblue/go-sh" + "github.com/google/goexpect" +) + +func main() { + // exit early if no sessions with my username are found + currentUser, _ := sh.Command("who").Command("grep", "my_username").Output() + if currentUser == nil { + os.Exit(1) + } + + // info about the coffee machine + coffeeMachineIP := "10.10.42.42" + password := "1234" + passwordPrompt := "Password: " + delayBeforeBrew := 17 * time.Second + delay := 24 * time.Second + + // timeout for the telnet prompts + timeout := 10 * time.Minute + + // sleep 17 seconds before brewing coffee + time.Sleep(delayBeforeBrew) + + // spawn a new telnet session with the coffee machine + t, _, err := expect.Spawn(fmt.Sprintf("telnet %s", coffeeMachineIP), -1) + if err != nil { + log.Fatal(err) + } + defer t.Close() + + t.Expect(regexp.MustCompile(passwordPrompt), timeout) + t.Send(password + "\n") + t.Expect(regexp.MustCompile("telnet>"), timeout) + t.Send("sys brew\n") + time.Sleep(delay) + t.Expect(regexp.MustCompile("telnet>"), timeout) + t.Send("sys pour\n") + t.Expect(regexp.MustCompile("telnet>"), timeout) + t.Send("exit\n") +} From 0ce706d30a80b511635a5b6414957e2921ab06bb Mon Sep 17 00:00:00 2001 From: linbudu599 Date: Sat, 18 Jan 2020 15:59:35 +0800 Subject: [PATCH 59/63] add simplified chinese README --- README.md | 3 +++ README.zh-CN.md | 59 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 README.zh-CN.md diff --git a/README.md b/README.md index bfda095d..8b46c69d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ + +English | [简体中文](./README.zh-CN.md) + # Hacker Scripts Based on a _[true diff --git a/README.zh-CN.md b/README.zh-CN.md new file mode 100644 index 00000000..3d07a559 --- /dev/null +++ b/README.zh-CN.md @@ -0,0 +1,59 @@ +# Hacker Scripts + +根据 *[真实故事](https://www.jitbit.com/alexblog/249-now-thats-what-i-call-a-hacker/)* 改编: + +> xxx: 是这样的,我们的构建工程师离职去了另外一家公司,这货基本算是生活在终端里。 你知道么,这人热爱Vim,用Dot作图,甚至用MarkDown来写维基帖子...,如果有什么事情要花上他超过90秒,她一定会整个脚本来让这件事变得“自动化”。 + +> xxx: 我们现在坐在他的工位上,看着他留下来的这些,呃,“遗产”? + +> xxx: 我觉得你们会喜欢这些的 + +> xxx: [`smack-my-bitch-up.sh(拍老婆马屁脚本)`](https://github.com/NARKOZ/hacker-scripts/blob/master/smack-my-bitch-up.sh) - 它会给他的老婆(很明显是他老婆)发送一条“今晚要加班了”的短信,再自动从文本库中随机地选择一条理由。这个脚本被设置为定时触发,而且只有在工作日晚9点以后,服务器上还有他登陆的SSH进程在运行时才会执行。 + +> xxx: [`kumar-asshole.sh(库马尔个傻*)`](https://github.com/NARKOZ/hacker-scripts/blob/master/kumar-asshole.sh) - 这个脚本会自动扫描邮箱,如果发现其中有库马尔(库马尔是我们客户公司的一位数据库管理员)发来的邮件,就会在其中寻找关键字如“求助”,“遇到麻烦了”,“抱歉”等等,如果发现了这些关键字,这个脚本会通过SSH连接上客户公司的服务器,把中间数据库(staging database)回滚到最新一次的可用备份。然后它会给邮件发送回复,“没事了哥们,下次小心点哈”。 + +> xxx: [`hangover.sh(宿醉)`](https://github.com/NARKOZ/hacker-scripts/blob/master/hangover.sh) - 同样是个定时执行的任务,被设置为在特定日期触发,它会自动发送诸如“今天不太舒服”或“今天我在家上班”之类的邮件,同样会从文本库里随机选取一条理由。这个任务会在工作日清晨8点45分以后服务器上仍然没有可交互的SSH进程时真正执行。 + +> xxx: (最牛的就是接下来这个) [`fucking-coffee.sh(**的咖啡)`](https://github.com/NARKOZ/hacker-scripts/blob/master/fucking-coffee.sh) - 这个脚本在启动之后,会先等待恰好17秒(!),然后启动一个登录进程连接到我们的咖啡机(淦,我们之前完全不知道我们的咖啡机是联网的,上面还运行着Linux系统,甚至还跑着TCP socket连接!),然后它会发送类似“系统!开始煮咖啡!”之类的消息,结果这条消息会让咖啡机开始工作,煮一杯 中杯大小、半咖啡因的拿铁,再等待恰好24秒(!)后,才倒进咖啡杯里。这些时间加起来刚好就是这位程序员从自己的工位走到机器前要的时间。 + +> xxx: 天了噜我要把这些保留下来。 + +原文: http://bash.im/quote/436725 (俄语) + +欢迎使用其它语言来实现 (Python, Perl, Shell等等)并提交PR。 + +## 用法 + +你需要以下这些环境变量: + +```bash +# used in `smack-my-bitch-up` and `hangover` scripts +TWILIO_ACCOUNT_SID=ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +TWILIO_AUTH_TOKEN=yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy + +# used in `kumar_asshole` script +GMAIL_USERNAME=admin@example.org +GMAIL_PASSWORD=password +``` + +为了执行Ruby脚本,你需要安装gems: `gem install dotenv twilio-ruby gmail` + +## 定时任务 + +```bash +# Runs `smack-my-bitch-up.sh` monday to friday at 9:20 pm. +20 21 * * 1-5 /path/to/scripts/smack-my-bitch-up.sh >> /path/to/smack-my-bitch-up.log 2>&1 + +# Runs `hangover.sh` monday to friday at 8:45 am. +45 8 * * 1-5 /path/to/scripts/hangover.sh >> /path/to/hangover.log 2>&1 + +# Runs `kumar-asshole.sh` every 10 minutes. +*/10 * * * * /path/to/scripts/kumar-asshole.sh + +# Runs `fucking-coffee.sh` hourly from 9am to 6pm on weekdays. +0 9-18 * * 1-5 /path/to/scripts/fucking-coffee.sh +``` + +------ + +代码的使用遵循WTFPL(Do What The Fuck You Want To Public License)协议。 \ No newline at end of file From 9cb4a2e49dd7f614b901066c9e3a3ccb2255558e Mon Sep 17 00:00:00 2001 From: Meyers Tom Date: Sun, 23 Feb 2020 20:15:21 +0200 Subject: [PATCH 60/63] Fixed Delay Typo's in fucking_coffee.py (#187) --- python/fucking_coffee.py | 2 +- python3/fucking_coffee.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python/fucking_coffee.py b/python/fucking_coffee.py index a6ea5e94..82609323 100755 --- a/python/fucking_coffee.py +++ b/python/fucking_coffee.py @@ -22,7 +22,7 @@ # Make some coffee! con.write("sys brew\n") -time.sleep(64) +time.sleep(24) # love the smell! con.write("sys pour\n") diff --git a/python3/fucking_coffee.py b/python3/fucking_coffee.py index 0268b79a..b3007804 100755 --- a/python3/fucking_coffee.py +++ b/python3/fucking_coffee.py @@ -24,7 +24,7 @@ def main(): conn.write(COFFEE_MACHINE_PASS) conn.write('sys brew') - time.sleep(64) + time.sleep(24) conn.write('sys pour') conn.close() From 91f0a00c5542ed89495f008d115e92705c3a01ca Mon Sep 17 00:00:00 2001 From: Witcher01 Date: Tue, 14 Apr 2020 17:34:57 +0200 Subject: [PATCH 61/63] code cleanup cleaned up code in 'KumarAsshole.java'. fixed confusing indentation and newlines for better readability. --- java/KumarAsshole.java | 40 +++++++++++++--------------------------- 1 file changed, 13 insertions(+), 27 deletions(-) diff --git a/java/KumarAsshole.java b/java/KumarAsshole.java index 24471c9e..cbbd97a4 100644 --- a/java/KumarAsshole.java +++ b/java/KumarAsshole.java @@ -1,4 +1,3 @@ - import java.io.File; import java.io.FileInputStream; import java.util.*; @@ -19,15 +18,13 @@ public static void main(String[] args) { public void read() { Properties props = new Properties(); - - //modify below properties to your details - String host = "smtp.gmail.com"; - String username = "yourmailaddress@example.com goes here"; - String password = "your password goes here "; - String Kumar_mail = "the mail address to be replied to !"; - - try { + //modify below properties to your details + String host = "smtp.gmail.com"; + String username = "yourmailaddress@example.com goes here"; + String password = "your password goes here "; + String Kumar_mail = "the mail address to be replied to !"; + try { Session session = Session.getDefaultInstance(props, null); Store store = session.getStore("imaps"); @@ -39,21 +36,16 @@ public void read() { Message messages[] = inbox.search(new FlagTerm(new Flags(Flags.Flag.SEEN), false)); for (int i = 0; i < messages.length; i++) { - if (messages[i].getFrom()[0].toString().contains(Kumar_mail)) { - String bodytext = null; Object content = messages[i].getContent(); if (content instanceof String) { bodytext = (String) content; - } else if (content instanceof Multipart) { - Multipart mp = (Multipart) content; BodyPart bp = mp.getBodyPart(mp.getCount() - 1); bodytext = (String) bp.getContent(); - } Pattern pattern = Pattern.compile("sorry|help|wrong", Pattern.CASE_INSENSITIVE); @@ -61,7 +53,6 @@ public void read() { // check all occurance if (matcher.find()) { - Properties props1 = new Properties(); Address[] tomail; @@ -73,23 +64,18 @@ public void read() { msg.setSubject("Database fixes"); msg.setText("No problem. I've fixed it. \n\n Please be careful next time."); Transport t = null; - t = session.getTransport("smtps"); - t.connect(host, username, password); - t.sendMessage(msg, msg.getAllRecipients()); - - + t = session.getTransport("smtps"); + t.connect(host, username, password); + t.sendMessage(msg, msg.getAllRecipients()); + } + } } - - } - } inbox.close(true); store.close(); - }catch(Exception e) - { - + } catch(Exception e) { e.printStackTrace(); } } -} \ No newline at end of file +} From 2be4a07f740ab4cf2ba35518cf00781dec6b3d98 Mon Sep 17 00:00:00 2001 From: ONEmoertime <51313428+ONEmoertime@users.noreply.github.com> Date: Thu, 20 Aug 2020 15:57:58 +0800 Subject: [PATCH 62/63] Update README.zh-CN.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In Chinese, the translation of "he" is "他" instead of "她",“她”is"she" --- README.zh-CN.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.zh-CN.md b/README.zh-CN.md index 3d07a559..b3f184d6 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -2,7 +2,7 @@ 根据 *[真实故事](https://www.jitbit.com/alexblog/249-now-thats-what-i-call-a-hacker/)* 改编: -> xxx: 是这样的,我们的构建工程师离职去了另外一家公司,这货基本算是生活在终端里。 你知道么,这人热爱Vim,用Dot作图,甚至用MarkDown来写维基帖子...,如果有什么事情要花上他超过90秒,她一定会整个脚本来让这件事变得“自动化”。 +> xxx: 是这样的,我们的构建工程师离职去了另外一家公司,这货基本算是生活在终端里。 你知道么,这人热爱Vim,用Dot作图,甚至用MarkDown来写维基帖子...,如果有什么事情要花上他超过90秒,他一定会整个脚本来让这件事变得“自动化”。 > xxx: 我们现在坐在他的工位上,看着他留下来的这些,呃,“遗产”? @@ -56,4 +56,4 @@ GMAIL_PASSWORD=password ------ -代码的使用遵循WTFPL(Do What The Fuck You Want To Public License)协议。 \ No newline at end of file +代码的使用遵循WTFPL(Do What The Fuck You Want To Public License)协议。 From f394120de09a86e59ee2eebb455f1205c2c0b188 Mon Sep 17 00:00:00 2001 From: Ash Jindal Date: Mon, 18 Jul 2022 09:48:28 +0100 Subject: [PATCH 63/63] Add archive.org link for the dead bash.im link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8b46c69d..00d6deef 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ story](https://www.jitbit.com/alexblog/249-now-thats-what-i-call-a-hacker/)_: > xxx: holy sh*t I'm keeping those -Original: http://bash.im/quote/436725 (in Russian) +Original: http://bash.im/quote/436725 (in Russian) (Archive.org [link](https://web.archive.org/web/20210226092253/http://bash.im/quote/436725)) Pull requests with other implementations (Python, Perl, Shell, etc) are welcome. ## Usage