{"id":459,"date":"2011-08-31T09:04:07","date_gmt":"2011-08-31T17:04:07","guid":{"rendered":"http:\/\/www.plasma2002.com\/blog\/?p=459"},"modified":"2016-07-28T10:14:03","modified_gmt":"2016-07-28T18:14:03","slug":"partyscroller","status":"publish","type":"post","link":"https:\/\/www.plasma2002.com\/blog\/2011\/08\/31\/partyscroller\/","title":{"rendered":"Party Scroller"},"content":{"rendered":"<h3 class=\"main\" style=\"color: #000000;\">Those jumbo screens at concerts that display your text messages can be a lot of fun. Wouldn&#8217;t it be great if you could have the same thing for your own parties or social gatherings? Well I tested that question. As it turns out, guests love it<\/h3>\n<h3><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-462\" src=\"http:\/\/www.plasma2002.com\/blog\/wp-content\/uploads\/2014\/06\/1272691_10151650371395108_630911476_o.jpg\" alt=\"1272691_10151650371395108_630911476_o\" width=\"700\" height=\"489\" srcset=\"https:\/\/www.plasma2002.com\/blog\/wp-content\/uploads\/2014\/06\/1272691_10151650371395108_630911476_o.jpg 700w, https:\/\/www.plasma2002.com\/blog\/wp-content\/uploads\/2014\/06\/1272691_10151650371395108_630911476_o-300x209.jpg 300w\" sizes=\"auto, (max-width: 700px) 100vw, 700px\" \/><\/h3>\n<p><iframe loading=\"lazy\" title=\"Party Scroller\" width=\"648\" height=\"486\" src=\"https:\/\/www.youtube.com\/embed\/PwKPiTD1jC0?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe><\/p>\n<p>&nbsp;<\/p>\n<h1>Why<\/h1>\n<hr \/>\n<p>&nbsp;<\/p>\n<p style=\"color: #000000;\"><img loading=\"lazy\" decoding=\"async\" class=\"alignright size-full wp-image-460\" src=\"http:\/\/www.plasma2002.com\/blog\/wp-content\/uploads\/2014\/06\/concertWall.jpg\" alt=\"concertWall\" width=\"284\" height=\"207\" \/>I&#8217;ve always loved the idea of sending messages to the big screens you usually find at concerts and other large events. I figured it could be scaled down, while still being just as entertaining. It may not have one of those spiffy 5-digit phone numbers, but the Google Voice number that it uses works just as well &#8211; especially since it also works as a vanity number for my handle \ud83d\ude42<\/p>\n<p style=\"color: #000000;\">After testing the sign at a party held at home, I noticed that people really seemed to enjoy it. One part of it that led to people enjoying it was the fact that the messages were anonymous. While it would have been really easy to make the sign show who the message was from, if theres one thing I&#8217;ve learned from the internet, it&#8217;s that people love being anonymous. Leaving a message that your peers can see, without knowing who wrote it, will always invoke the most curious behavior.<\/p>\n<p style=\"color: #000000;\">With any anonymity, comes that behavior. I already knew that, so I took the liberty to set up some bad-word filters to start replacing parts of messages. You can see that list in one of the scripts below &#8211; which is most likely causing Google to flag my page as inappropriate, but I digress&#8230; Not only did this keep the board clean, but it was even more entertaining to people to see such &#8216;odd&#8217; words come up in their messages. It only kept people texting more and more to see what other replacements they could figure out.<\/p>\n<p style=\"color: #000000;\">All in all, it really seems this experiment was a success. People loved it, and I loved setting it up. I highly recommend you do the same for your next party or other event. As long as your guests have their cell phones, they&#8217;re definitely going to be tempted to send something.<\/p>\n<p>&nbsp;<\/p>\n<h1>Technical Details<\/h1>\n<hr \/>\n<p style=\"color: #000000;\">The Party Scroller makes use of several servers<!--more--> and several scripts to get a message from your phone to the sign. Check out the flowchart for a quick visual reference. Basically, heres the gist of it: The user sends a text message from their phone to my Google Voice number, which will then send an email out to a special email address which pipes the email into a PHP script. The PHP script will extract the necessary data from the email, and put it into a database. Meanwhile, another computer is continually checking the database for a new message every 20 seconds. When it sees a new one, it will grab it from the database and display it on the board.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-461\" src=\"http:\/\/www.plasma2002.com\/blog\/wp-content\/uploads\/2014\/06\/flowchart.png\" alt=\"flowchart\" width=\"750\" height=\"256\" srcset=\"https:\/\/www.plasma2002.com\/blog\/wp-content\/uploads\/2014\/06\/flowchart.png 750w, https:\/\/www.plasma2002.com\/blog\/wp-content\/uploads\/2014\/06\/flowchart-300x102.png 300w\" sizes=\"auto, (max-width: 750px) 100vw, 750px\" \/><\/p>\n<p>&nbsp;<\/p>\n<h1>Instructions<\/h1>\n<hr \/>\n<p style=\"color: #000000;\">Want to set something like this up yourself? You will need the following items:<\/p>\n<ul style=\"color: #000000;\">\n<li>A\u00a0<a style=\"color: black;\" href=\"http:\/\/voice.google.com\/\" target=\"blank\">Google Voice<\/a>\u00a0account<\/li>\n<li>An email address you can pipe to a script (if your host has cPanel, you can do this)<\/li>\n<li>A database server<\/li>\n<li>A computer at home able to run PHP\/PERL (I used Ubuntu, but OS shouldn&#8217;t matter)<\/li>\n<li>An LED sign that you can hook up to your computer. I am using a Beta Brite<\/li>\n<\/ul>\n<h3 style=\"color: #000000;\">Step 1: Creating the Email Scripts<\/h3>\n<p><a style=\"color: black;\" href=\"http:\/\/sudocode.net\/sources\/includes\/class-email-php\/\" target=\"_blank\">Download this PHP email class<\/a>, which was written by Arvin Castro. It can be found on his site,<a style=\"color: black;\" href=\"http:\/\/sudocode.net\/sources\/includes\/class-email-php\/\" target=\"_blank\">SudoCode.net<\/a>. Upload this class to your own web host. The following script uses it, so place it wherever you want the rest of your code.<\/p>\n<p style=\"color: #000000;\">Edit the script below. Put in your database name, password, host, etc, then upload it to the same directory you put the above email class in. This script is the script that emails will get sent to. It is going to analyze the contents of the emails and put them into your database.<\/p>\n<p>&nbsp;<\/p>\n<pre>#!\/usr\/local\/bin\/php\r\n<!--?php $realEmailAddress = \"your@email.com\"; \/\/Your actual email address. NOT the google voice one. $saveIndividualEmails = 0; \/\/Set to 1 to log every email received to a text file in this directory. Useful for debugging $saveLogFile = 0; \/\/Set to 1 to save incoming stats to a log file in this directory. Useful for debugging $dbHost = \"localhost\"; \/\/Wheres your db host? Usually localhost $dbName = \"partyScroller\"; \/\/Which database? $dbUser = \"brianGaut\"; \/\/Database username that has access to above database $dbPass = \"randomPassWord\"; \/\/Db users password? chdir(dirname(__FILE__)); require_once 'class.email.php'; \/\/Time that the script received the email $emailTime = time(); \/\/ Parse incoming email from STDIN $email = email::parseSTDIN(); if($saveIndividualEmails == 1){ \/\/Save the RAW email to a file $fh = fopen($emailTime . \".txt\", 'w'); fwrite($fh, $email--->raw);\r\n\tfclose($fh);\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\/\/ Check if verification email was received. Will in reality only be used one time\r\n\tif($email-&gt;getSenderEmail() == 'account-verification-noreply@google.com') {\r\n\t\t\/\/ Forward verification email to your email address\r\n\t\tmail($realEmailAddress, 'Google Email Verification', $email-&gt;getTextContent(), 'from: '.$email-&gt;getRecipientEmail());\r\n\t\tdie();\r\n\t}\r\n\r\n\r\n\/\/Parse the email FROM url for GV specific variables\r\n\t$parsedSenderUrl = parse_url('http:\/\/'.$email-&gt;getSenderEmail());\r\n\r\n\r\n\r\n\r\n\r\n\r\n\/\/ Check if the email came from Google Voice\r\n\tif('txt.voice.google.com' == $parsedSenderUrl['host']) {\r\n\t\t$isFromGv = 1;\r\n\t}else{\r\n\t\t$isFromGv = 0;\r\n\t}\r\n\r\n\r\n\r\n\r\n\/\/ Splice the sender's email address to get the details\r\n\/\/ format: googlevoicenumber.sendernumber.messageid@txt.voice.google.com\r\n\tlist($recipient, $sender, $messageid) = explode('.', $parsedSenderUrl['user']);\r\n\t$message = trim($email-&gt;getTextContent());\r\n\/\/ $messageid  - message id used by GVoice for threading messages. This is NOT unique!!!\r\n\/\/ $recipient  - your google voice number\r\n\/\/ $sender     - phone number of sender\r\n\/\/ $message    - content of the SMS message\r\n\r\n\r\n\r\n\r\n\/\/Try to get rid of that stupid GV generated tagline. the 'Sent using SMS-to-email' line at the end\r\n\t$txtToFind = \"\\n\\n--\\nSent\";\r\n\t$start = strpos($message, $txtToFind);\r\n\tif($start &gt; 0){\r\n\t\t$message = substr($message,0,$start);\r\n\t}\r\n\r\n\r\n\r\n\r\n\/\/Lets put that info into the database\r\n\r\n\t$conn = mysql_connect($dbHost , $dbUser ,$dbPass );\r\n\t$result = mysql_select_db($dbName , $conn);\r\n\r\n\t$messageId = mysql_real_escape_string(trim($messageid));\r\n\t$toNumber = mysql_real_escape_string(trim($recipient));\r\n\t$fromNumber = mysql_real_escape_string(trim($sender));\r\n\t$smsText = mysql_real_escape_string(trim($message));\r\n\r\n\t$sql = (\"\r\n\t\tINSERT INTO\r\n\t\t\t`txtMessages`\r\n\t\t\t(`username`, `time`, `message`)\r\n\t\tVALUES\r\n\t\t\t('\".$fromNumber.\"','\".$emailTime.\"','\".$smsText.\"');\r\n\t\t\");\r\n\r\n\tif($conn){\r\n\t\tmysql_query($sql);\r\n\t\t$latestRow = mysql_insert_id();\r\n\t}\r\n\r\n\r\n\r\n\r\n\r\n\r\nif($saveLogFile == 1){\r\n\/\/Log the details into the logfile\r\n$data = (\"\r\n\tTime: \" . $emailTime . \"\r\n\tMID: \" . $messageid . \"\r\n\tTo: \". $recipient . \"\r\n\tFrom: \" . $sender . \"\r\n\tMSG: \" . $message . \"\r\n\tInserted Row ID: \".$latestRow.\"\r\n\tSQL: \".$sql.\"\r\n\t\");\r\n\r\n\t$fh = fopen(\"log.txt\", 'a+');\r\n\tfwrite($fh, $data);\r\n\tfclose($fh);\r\n}\r\n\r\n?&gt;\r\n<\/pre>\n<p style=\"color: #000000;\">Note that this script was adapted from a similar one also written by Arvin Castro. His original script can be found on his article about\u00a0<a style=\"color: black;\" href=\"http:\/\/sudocode.net\/article\/190\/receiving-incoming-smstext-messages-from-google-voice-in-php\/\" target=\"_blank\">receiving incoming text messages from Google Voice<\/a>, which helped me out a lot on getting this LED sign working<\/p>\n<h3 style=\"color: #000000;\">Step 2: Designing the Database<\/h3>\n<p style=\"color: #000000;\">By default, the script above uses a database table called &#8216;txtMessages&#8217;. You can run the following SQL to create that table.<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"code\" style=\"color: #000000;\">CREATE TABLE txtMessages (\r\n\t`m_id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, data INT(11),\r\n\t`message` VARCHAR(512),\r\n\t`username` VARCHAR(32),\r\n\t`time` INT(11),\r\n\t`last_displayed` INT(11)\r\n\t);\r\n<\/pre>\n<p>&nbsp;<\/p>\n<h3 style=\"color: #000000;\">Step 3: Configuring Email<\/h3>\n<p style=\"color: #000000;\">These instructions will show you how to create a new email address and configure it to send all incoming emails to the email parsing script that we uploaded earlier. It assumes that you are using a web host which gives you access to cPanel.<\/p>\n<ul style=\"color: #000000;\">\n<li>On your cPanel homepage, click the &#8216;EMail Forwarders&#8217; link<\/li>\n<li>Click &#8216;Add Forwarder&#8217;<\/li>\n<li>Enter a new email address to use. The only thing that will be using this address is Google Voice<\/li>\n<li>Under &#8216;Destination&#8217;, select &#8216;Pipe to a Program&#8217;, and enter the path to the email parsing script above. Make sure you have the path correct, as if its not, it will be very hard to tell when and where things are going wrong<\/li>\n<li>After adding the email address, it might be a good idea to click &#8216;Trace&#8217;, just to make sure it works<\/li>\n<\/ul>\n<h3 style=\"color: #000000;\">Step 4: Configuring Google Voice<\/h3>\n<ul style=\"color: #000000;\">\n<li>Go to your Google Voice settings page and click the &#8216;Voicemail &amp; Text&#8217; tab<\/li>\n<li>Click the &#8216;Add a new email address&#8217; link. The link is in the Voicemail Notifications area, but this is still what we want to use<\/li>\n<li>Enter the email address you set up in step 3 down in the &#8216;Add an alternate email address&#8217; area. Google will now send a verification email to the new email address. As long as your script is set up correctly, it should forward the verification email to your real email account<\/li>\n<li>Go check your email and click the link in the verification email<\/li>\n<li>Back in GV settings, switch the dropdown box to the new email address you set up (still in Voicemail Notifications).\u00a0<b>UNCHECK<\/b>\u00a0the box asking to email voicemails to this email address<\/li>\n<li>Down on the Text Forwarding area, check the box labeled &#8216;Forward text messages to my email&#8217;. Click Save Changes<\/li>\n<li>Your alternate email address, the one we just created, should show up in the text forwarding area now<\/li>\n<\/ul>\n<h3 style=\"color: #000000;\">Step 5: Controlling the L.E.D. Sign<\/h3>\n<p style=\"color: #000000;\">We now need to set up a script that will send messages to the LED sign. This script below is specifically for a Beta Brite LED Sign. If you are using another sign, all is not lost. You will simply need to change this script, and this script only.<\/p>\n<pre class=\"code\" style=\"color: #000000;\">#!\/usr\/bin\/perl\r\n\r\nmy $message = $ARGV[0];\r\nmy $message_type = $ARGV[1];\r\n\r\nmy $serial_port_to_use = \"\/dev\/ttyS0\";\r\n\r\n\r\n($second, $minute, $hour, $dayOfMonth, $month, $yearOffset, $dayOfWeek, $dayOfYear, $daylightSavings) = localtime();\r\nif(length($minute) &lt; 2){\r\n\t$minute = \"0\" . $minute;\r\n}\r\nmy $theTime = \"$hour:$minute\";\r\n\r\n\r\n\r\n#BETABRITE VARIABLES\r\n\r\n\r\n\r\n\tmy $NUL            = \"\\0\\0\\0\\0\\0\\0\";       # NUL - Sending 6 nulls for wake up sign and set baud neg.\r\n\tmy $SOH            = \"\\x01\";               # SOH - Start of header\r\n\tmy $TYPE           = \"Z\";                       # Type Code - Z = All signs. See Protocol doc for more info\r\n\tmy $SIGN_ADDR      = \"00\";                      # Sign Address - 00 = broadcast, 01 = sign address 1, etc\r\n\tmy $STX            = \"\\x02\";               # STX - Start of Text character\r\n\t# These are other useful variables\r\n\tmy $ETX            = \"\\x03\";            # End of TeXt\r\n\tmy $ESC            = \"\\x1b\";            # Escape character\r\n\tmy $EOT            = \"\\004\";            # End of transmission\r\n\t# We group some of the variables above to make life easy.\r\n\t# This leaves us 2 type of init strings we can add to the front of our frame.\r\n\tmy $INIT=\"$NUL$SOH$TYPE$SIGN_ADDR$STX\";         # Most used.\r\n\tmy $INIT_NOSTX=\"$NUL$SOH$TYPE$SIGN_ADDR\";               # Used for nested messages.\r\n\t###\r\n\tmy $WRITE =\"A\"; # Write TEXT file\r\n\t###\r\n\tmy $LABEL = \"A\"; #File A\r\n\t###\r\n\tmy $DPOS=\" \"; # Leave as a space for BetaBrite one line sign\r\n\t###\r\n\tmy $ROTATE =\"A\"; # Message travels right to left.\r\n\tmy $COMPRESSED =\"t\"; # Skinny letters that rotate as above\r\n\tmy $HOLD =\"b\"; # Message remains stationary.\r\n\tmy $FLASH =\"c\"; # Message remains stationary and flashes\r\n\r\n\t### COLORS\r\n\tmy $RED = chr(28) . \"1\";\r\n\tmy $GREEN = chr(28) . \"2\";\r\n\tmy $YELLOW = chr(28) . \"3\";\r\n\tmy $RED_DIM = chr(28) . \"4\";\r\n\tmy $GREEN_DIM = chr(28) . \"5\";\r\n\tmy $YELLOW_DIM = chr(28) . \"6\";\r\n\tmy $ORANGE = chr(28) . \"7\";\r\n\tmy $YELLOW_LIGHT = chr(28) . \"8\";\r\n\tmy $RAINBOW = chr(28) . \"9\";\r\n\tmy $RAINBOW_MOVING = chr(28) . \"A\";\r\n\tmy $RAINBOW_FADE = chr(28) . \"B\";\r\n\tmy $RAINBOW_CYCLE = chr(28) . \"C\";\r\n\r\n\t###\r\n\r\n$message =~ s\/\\[G\\]\/$GREEN\/gi;\r\n$message =~ s\/\\[GD\\]\/$GREEN_DIM\/gi;\r\n$message =~ s\/\\[R\\]\/$RED\/gi;\r\n$message =~ s\/\\[RD\\]\/$RED_DIM\/gi;\r\n$message =~ s\/\\[Y\\]\/$YELLOW\/gi;\r\n$message =~ s\/\\[YD\\]\/$YELLOW_DIM\/gi;\r\n$message =~ s\/\\[YL\\]\/$YELLOW_LIGHT\/gi;\r\n$message =~ s\/\\[O\\]\/$ORANGE\/gi;\r\n$message =~ s\/\\[R1\\]\/$RAINBOW\/gi;\r\n$message =~ s\/\\[R2\\]\/$RAINBOW_MOVING\/gi;\r\n$message =~ s\/\\[R3\\]\/$RAINBOW_FADE\/gi;\r\n$message =~ s\/\\[R4\\]\/$RAINBOW_CYCLE\/gi;\r\n\r\n$message =~ s\/\\[T\\]\/$theTime\/gi;\r\n\r\n\r\n\r\n\r\n\r\n\topen(BETABRITE, \"&gt;\" . $serial_port_to_use);\r\n\t#set a message\r\n\r\n\r\n####THIS RESETS THE SIGN MEMORY:\r\n####print BETABRITE \"$NUL\" . \"$SOH\" . \"$TYPE\" . \"$SIGN_ADDR\" .  \"$STX\" . \"E\\$\" . \"$EOT\";\r\n\r\n####THIS MAKES THE SIGN BEEP:\r\n####print BETABRITE \"$NUL\" . \"$SOH\" . \"$TYPE\" . \"$SIGN_ADDR\" .  \"$STX\" . \"E(0\" . \"$EOT\";\r\n\r\n####Puts up a message\r\n\r\nmy $MODE = $ROTATE;\r\nif($message_type eq \"f\"){\r\n\t$MODE = $FLASH;\r\n}\r\nif($message_type eq \"h\"){\r\n\t$MODE = $HOLD;\r\n}\r\n\r\n\r\nprint BETABRITE \"$INIT\" . \"AA\" . \"$ESC\" . \"$DPOS\" . \"$MODE\" . \"$GREEN\" . \"$message\" . \"$EOT\";\r\n\r\n\r\n\r\n\r\n\r\n\tclose(BETABRITE);\r\n#print \"Message has been sent to board: \" . $message . \"\\n\";\r\n<\/pre>\n<p style=\"color: #000000;\">Save the above perl script as &#8216;led.pl&#8217; on the computer that your LED sign is plugged into. Give it execute rights. (chmod +x led.pl)<\/p>\n<h3 style=\"color: #000000;\">Step 6: Party Scrolling<\/h3>\n<p style=\"color: #000000;\">The file script is a php script that will be run via command line and continuously loop, looking for new messages on the database. If it sees one, it will do some word filtering, then pass the message to the above perl script, which actually puts it on the sign.<\/p>\n<pre class=\"code\" style=\"color: #000000;\">&lt;?\r\n$rightNow = time();\r\n\r\n\/*\r\nThis script will scroll text messages onto a Betabrite LED board.\r\nIt obtains the messages from a remote database. The messages are\r\nput into the database from an email piped into another php script.\r\nThe text messages get sent in an email by Google Voice.\r\n\r\nWritten by Brian Gaut - http:\/\/www.plasma2002.com\r\n8-26-2011\r\n*\/\r\n\r\n\r\n\/\/Show messages up to X seconds old. Make sure to adjust for server &lt;-&gt; server time differences, if any\r\n\t$debugIt = 1; \/\/1 = lots of information on command line, 0 = only message changes\r\n\r\n\/\/Show messages up to X seconds old. Make sure to adjust for server &lt;-&gt; server time differences, if any\r\n\t$ageLimit = 60*15; \/\/15 mins\r\n\r\n\/\/How often to check the database and update the sign\r\n\t$updateEvery = \"20\"; \/\/Every 20 seconds\r\n\r\n\/\/Where is the script that sends messages to the LED sign?\r\n\t$pathToLedScript = \"\/home\/brianGaut\/myScripts\/led.pl\";\r\n\r\n\/\/Database Server details\r\n\t$mainServer = \"yourDbServer.com\";\r\n\t$mainUser = \"dbUserName\";\r\n\t$mainPassword = \"dbUserPassword\";\r\n\t$mainDatabase = \"partyScroller\";\r\n\r\n\r\n\r\n\r\n\r\nfunction connect(){\r\n\tglobal $conn; \/\/Only one persistant connection. No need for db class most likely\r\n\tglobal $mainServer;\r\n\tglobal $mainUser;\r\n\tglobal $mainPassword;\r\n\tglobal $mainDatabase;\r\n\r\n\t\/\/Use a persistant connection\r\n\t$conn = mysql_pconnect($mainServer, $mainUser,$mainPassword)\r\n\t\tor die(\"MySQL -Connection- FAILED!\");\r\n\r\n\t$result = mysql_select_db($mainDatabase, $conn)\r\n\t\tor die(\"MySQL -db Selection- FAILED!\");\r\n\treturn $conn;\r\n}\r\n\r\nfunction mysqlit($sql){\r\n\tglobal $conn;\r\n\tif(!$conn){\r\n\t\t$conn = connect();\r\n\t}\r\n\t$result = mysql_query($sql, $conn);\r\n\treturn $result;\r\n\tmysql_free_result($result);\r\n}\r\n\r\nfunction dbg($x){\r\n\tglobal $debugIt;\r\n\tif($debugIt == 1){\r\n\t\techo $x . \"\\n\";\r\n\t}\r\n}\r\n\r\n\/\/Dont touch these. (Init'ing some vars)\r\n\t$lastUpdate = 0;\r\n\t$timeLimitCutoff = $rightNow - $ageLimit;\r\n\t$previousMessage = ''; \/\/For comparing\r\n\r\n\r\nfunction sendToSign($txt,$from){\r\n\tglobal $previousMessage;\r\n\r\n\t\/\/Lets clean up the text before we send it to the sign\r\n\t$message = ($txt);\r\n\r\n\t\/\/CHARACTER FILTERS\r\n\t$message = str_replace(\"\\$\", \"\\\\$\", $message);\r\n\t$message = str_replace(\"\\\\'\", \"'\", $message);\r\n\t$message = str_replace(\"\\\"\", \"'\", $message);\r\n\t$message = str_replace(\"#\", \"\\#\", $message);\r\n\t$message = str_replace(\"`\", \"'\", $message);\r\n\r\n\t\/\/BAD WORD FILTERS\r\n\t$message = str_ireplace(\"f u c k e r\",\"G e r b i l e r\", $message);\r\n\t$message = str_ireplace(\"gtfo\",\"Get outta my house\", $message);\r\n\t$message = str_ireplace(\"pudi\",\"Jello\", $message);\r\n\t$message = str_ireplace(\"puddi\",\"Jello\", $message);\r\n\t$message = str_ireplace(\"fucker\",\"Gerbiler\", $message);\r\n\t$message = str_ireplace(\"fucking\",\"Gerbiling\", $message);\r\n\t$message = str_ireplace(\"fuck\",\"Gerbil\", $message);\r\n\t$message = str_ireplace(\"asshole\",\"Nugget Hole\", $message);\r\n\t$message = str_ireplace(\"dumbass\",\"Nugget Hat\", $message);\r\n\t$message = str_ireplace(\" ass \",\"Nugget\", $message);\r\n\t$message = str_ireplace(\" ass.\",\"Nugget\", $message);\r\n\t$message = str_ireplace(\"bitches\",\"Noodles\", $message);\r\n\t$message = str_ireplace(\"bitching\",\"Noodling\", $message);\r\n\t$message = str_ireplace(\"bitchin\",\"Noodlin\", $message);\r\n\t$message = str_ireplace(\"bitch\",\"Noodle\", $message);\r\n\t$message = str_ireplace(\"cunt\",\"Chipootle\", $message);\r\n\t$message = str_ireplace(\"twat\",\"Chipootle\", $message);\r\n\t$message = str_ireplace(\"clit\",\"Chipootle\", $message);\r\n\t$message = str_ireplace(\"cock\",\"Sock Puppet\", $message);\r\n\t$message = str_ireplace(\"dick\",\"Sock Puppet\", $message);\r\n\t$message = str_ireplace(\"shit\",\"Playdough\", $message);\r\n\t$message = str_ireplace(\"tits\",\"Whoppers\", $message);\r\n\t$message = str_ireplace(\"titts\",\"Whoppers\", $message);\r\n\t$message = str_ireplace(\"titties\",\"Whoppers\", $message);\r\n\t$message = str_ireplace(\"boobs\",\"Whoppers\", $message);\r\n\t$message = str_ireplace(\"boobies\",\"Whoppers\", $message);\r\n\t$message = str_ireplace(\"jugs\",\"Whoppers\", $message);\r\n\t$message = str_ireplace(\"jugz\",\"Whoppers\", $message);\r\n\t$message = str_ireplace(\"knockers\",\"Whoppers\", $message);\r\n\t$message = str_ireplace(\"nigger\",\"Hot Carl\", $message);\r\n\t$message = str_ireplace(\"niga\",\"Hot Carl\", $message);\r\n\t$message = str_ireplace(\"nigga\",\"Hot Carl\", $message);\r\n\t$message = str_ireplace(\"faggot\",\"(...Im just some ignorant kid who thinks calling somebody gay makes me cool...)\", $message);\r\n\t$message = str_ireplace(\"fag\",\"(...Im just some ignorant kid who thinks calling somebody gay makes me cool...)\", $message);\r\n\r\n\r\n\tif($message != $previousMessage){\r\n\t\tif($message == \" \"){\r\n\t\t\techo \"[Blanking Sign]\\n\";\r\n\t\t}else{\r\n\t\t\techo \"Sending to sign via [\".$from.\"]: \" . $message . \"\\n\";\r\n\t\t}\r\n\r\n\t\t`perl \"$pathToLedScript\" \"$message\"`;\r\n\r\n\t}else{\r\n\t\tdbg(\"This was the same as the last message! Not doing anything\");\r\n\t}\r\n\r\n\t$previousMessage = $message;\r\n\r\n\r\n}\r\n\r\n\/\/This is the main loop that will continue until the script is killed\r\nwhile(1){\r\n\twhile(($rightNow - $lastUpdate) &gt; $updateEvery ){\r\n\t\tdbg(\"Its been \".$updateEvery.\" seconds! Looking for messages larger than \" . $timeLimitCutoff);\r\n\r\n\t\t\/\/Update our time vars\r\n\t\t$lastUpdate = $rightNow;\r\n\t\t$timeLimitCutoff = $rightNow - $ageLimit;\r\n\r\n\r\n\t\t$sql = (\"\r\n\t\t\tSELECT * FROM\r\n\t\t\t\t`txtMessages`\r\n\t\t\tWHERE\r\n\t\t\t\t`time` &gt; '\".$timeLimitCutoff.\"'\r\n\t\t\tORDER BY\r\n\t\t\t\t`last_displayed` ASC\r\n\t\t\tLIMIT 0,1\r\n\t\t\t\");\r\n\t\tif(!$result = mysqlit($sql)){\r\n\t\t\t\/\/it didnt work! db is probably down.\r\n\t\t\tdbg(\"Could not connect to database. Will try again later\");\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tif(!$row = mysql_fetch_array($result)){\r\n\t\t\t\/\/If the result is empty, then just blank out the sign\r\n\t\t\tdbg(\"No messages to display\");\r\n\t\t\tsendToSign(\" \",\"Nobody\");\r\n\t\t}else{\r\n\t\t\tdbg(\"Found a message to display\");\r\n\t\t\t$txtMessage = $row['message'];\r\n\r\n\t\t\t\/\/Is it a new message?\r\n\t\t\tif($row['last_displayed'] == \"0\"){\r\n\t\t\t\tdbg(\"Its brand new! Now pinging the notification page\");\r\n\r\n\t\t\t\t\/\/The below webpage is actually a page that simply plays\r\n\t\t\t\t\/\/a certain WAV file on the computers speakers.\r\n\t\t\t\texec(\"wget -O - http:\/\/192.168.0.37\/sound.php --quiet &gt; \/dev\/null &amp;\");\r\n\t\t\t}\r\n\r\n\t\t\t\/\/before we send the text to the sign, lets update the db row, saying we did it\r\n\t\t\t$updateSql = (\"UPDATE `txtMessages` SET `last_displayed` = '\".$rightNow.\"' WHERE `m_id` = '\".$row['m_id'].\"' LIMIT 1;\");\r\n\t\t\t\/\/whoops.... maybe i should have used a class, heh\r\n\r\n\t\t\tdbg(\"Updating last_displayed data for this message\");\r\n\t\t\tif(!$updateResult = mysqlit($updateSql)){\r\n\t\t\t\techo \"ERROR - Could not update last_displayed status for this message\\n\";\r\n\t\t\t}\r\n\t\t\tunset($updateResult); \/\/advice for others: use a db class! :P\r\n\r\n\r\n\t\t\t\/\/Ok, send the message to the sign function\r\n\t\t\tsendToSign($txtMessage,$row['username']);\r\n\r\n\r\n\t\t}\r\n\r\n\r\n\t}\r\n\t$rightNow = time(); \/\/Latest time\r\n\t\/\/Sleep for a sec, that way we dont overload our computer\r\n\t\/\/ with time() updates. (They totally add up quick)\r\n\tsleep(1);\r\n}\r\n\r\n\/\/And thats that :)\r\n\r\n?&gt;\r\n<\/pre>\n<p style=\"color: #000000;\">Save this file as &#8216;partyScroller.php&#8217; and as with the previous script, give it execute rights.<\/p>\n<h3 style=\"color: #000000;\">Step 7: RUN IT!<\/h3>\n<p style=\"color: #000000;\">To run your LED sign updater, just go into a shell or command prompt and run it with php.<\/p>\n<div class=\"code\" style=\"color: #000000;\">#&gt; php partyScroller.php<\/div>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Those jumbo screens at concerts that display your text messages can be a lot of fun. Wouldn&#8217;t it be great if you could have the same thing for your own parties or social gatherings? Well I tested that question. As it turns out, guests love it &nbsp; Why &nbsp; I&#8217;ve always loved the idea of [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[20,37,16,31],"tags":[],"class_list":["post-459","post","type-post","status-publish","format-standard","hentry","category-geek","category-portfolio","category-projects","category-top"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.2 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Party Scroller - Plasma2002<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"http:\/\/www.plasma2002.com\/partyscroller\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Party Scroller - Plasma2002\" \/>\n<meta property=\"og:description\" content=\"Those jumbo screens at concerts that display your text messages can be a lot of fun. Wouldn&#8217;t it be great if you could have the same thing for your own parties or social gatherings? Well I tested that question. As it turns out, guests love it &nbsp; Why &nbsp; I&#8217;ve always loved the idea of [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"http:\/\/www.plasma2002.com\/partyscroller\/\" \/>\n<meta property=\"og:site_name\" content=\"Plasma2002\" \/>\n<meta property=\"article:publisher\" content=\"http:\/\/facebook.com\/plasma2002\" \/>\n<meta property=\"article:published_time\" content=\"2011-08-31T17:04:07+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2016-07-28T18:14:03+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/www.plasma2002.com\/blog\/wp-content\/uploads\/2014\/06\/1272691_10151650371395108_630911476_o.jpg\" \/>\n<meta name=\"author\" content=\"Plasma2002\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Plasma2002\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"14 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"http:\/\/www.plasma2002.com\/blog\/2011\/08\/31\/partyscroller\/\",\"url\":\"http:\/\/www.plasma2002.com\/partyscroller\/\",\"name\":\"Party Scroller - Plasma2002\",\"isPartOf\":{\"@id\":\"http:\/\/www.plasma2002.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"http:\/\/www.plasma2002.com\/partyscroller\/#primaryimage\"},\"image\":{\"@id\":\"http:\/\/www.plasma2002.com\/partyscroller\/#primaryimage\"},\"thumbnailUrl\":\"http:\/\/www.plasma2002.com\/blog\/wp-content\/uploads\/2014\/06\/1272691_10151650371395108_630911476_o.jpg\",\"datePublished\":\"2011-08-31T17:04:07+00:00\",\"dateModified\":\"2016-07-28T18:14:03+00:00\",\"author\":{\"@id\":\"http:\/\/www.plasma2002.com\/blog\/#\/schema\/person\/a99fb575da6efea98db3e249b5e3f108\"},\"breadcrumb\":{\"@id\":\"http:\/\/www.plasma2002.com\/partyscroller\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"http:\/\/www.plasma2002.com\/partyscroller\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"http:\/\/www.plasma2002.com\/partyscroller\/#primaryimage\",\"url\":\"https:\/\/www.plasma2002.com\/blog\/wp-content\/uploads\/2014\/06\/1272691_10151650371395108_630911476_o.jpg\",\"contentUrl\":\"https:\/\/www.plasma2002.com\/blog\/wp-content\/uploads\/2014\/06\/1272691_10151650371395108_630911476_o.jpg\",\"width\":700,\"height\":489},{\"@type\":\"BreadcrumbList\",\"@id\":\"http:\/\/www.plasma2002.com\/partyscroller\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"http:\/\/www.plasma2002.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Party Scroller\"}]},{\"@type\":\"WebSite\",\"@id\":\"http:\/\/www.plasma2002.com\/blog\/#website\",\"url\":\"http:\/\/www.plasma2002.com\/blog\/\",\"name\":\"Plasma2002\",\"description\":\"Ramblings from the Fourth State of Matter\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"http:\/\/www.plasma2002.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"http:\/\/www.plasma2002.com\/blog\/#\/schema\/person\/a99fb575da6efea98db3e249b5e3f108\",\"name\":\"Plasma2002\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"http:\/\/www.plasma2002.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/cd4c32edd53cd00dd0feaf6d7abe80e169471f3c114539d040001015979afb5a?s=96&d=retro&r=r\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/cd4c32edd53cd00dd0feaf6d7abe80e169471f3c114539d040001015979afb5a?s=96&d=retro&r=r\",\"caption\":\"Plasma2002\"},\"description\":\"For my bio, please see http:\/\/www.plasma2002.com\/about\",\"sameAs\":[\"http:\/\/www.plasma2002.com\"],\"url\":\"https:\/\/www.plasma2002.com\/blog\/author\/plasma2002\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Party Scroller - Plasma2002","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"http:\/\/www.plasma2002.com\/partyscroller\/","og_locale":"en_US","og_type":"article","og_title":"Party Scroller - Plasma2002","og_description":"Those jumbo screens at concerts that display your text messages can be a lot of fun. Wouldn&#8217;t it be great if you could have the same thing for your own parties or social gatherings? Well I tested that question. As it turns out, guests love it &nbsp; Why &nbsp; I&#8217;ve always loved the idea of [&hellip;]","og_url":"http:\/\/www.plasma2002.com\/partyscroller\/","og_site_name":"Plasma2002","article_publisher":"http:\/\/facebook.com\/plasma2002","article_published_time":"2011-08-31T17:04:07+00:00","article_modified_time":"2016-07-28T18:14:03+00:00","og_image":[{"url":"http:\/\/www.plasma2002.com\/blog\/wp-content\/uploads\/2014\/06\/1272691_10151650371395108_630911476_o.jpg","type":"","width":"","height":""}],"author":"Plasma2002","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Plasma2002","Est. reading time":"14 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"http:\/\/www.plasma2002.com\/blog\/2011\/08\/31\/partyscroller\/","url":"http:\/\/www.plasma2002.com\/partyscroller\/","name":"Party Scroller - Plasma2002","isPartOf":{"@id":"http:\/\/www.plasma2002.com\/blog\/#website"},"primaryImageOfPage":{"@id":"http:\/\/www.plasma2002.com\/partyscroller\/#primaryimage"},"image":{"@id":"http:\/\/www.plasma2002.com\/partyscroller\/#primaryimage"},"thumbnailUrl":"http:\/\/www.plasma2002.com\/blog\/wp-content\/uploads\/2014\/06\/1272691_10151650371395108_630911476_o.jpg","datePublished":"2011-08-31T17:04:07+00:00","dateModified":"2016-07-28T18:14:03+00:00","author":{"@id":"http:\/\/www.plasma2002.com\/blog\/#\/schema\/person\/a99fb575da6efea98db3e249b5e3f108"},"breadcrumb":{"@id":"http:\/\/www.plasma2002.com\/partyscroller\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["http:\/\/www.plasma2002.com\/partyscroller\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"http:\/\/www.plasma2002.com\/partyscroller\/#primaryimage","url":"https:\/\/www.plasma2002.com\/blog\/wp-content\/uploads\/2014\/06\/1272691_10151650371395108_630911476_o.jpg","contentUrl":"https:\/\/www.plasma2002.com\/blog\/wp-content\/uploads\/2014\/06\/1272691_10151650371395108_630911476_o.jpg","width":700,"height":489},{"@type":"BreadcrumbList","@id":"http:\/\/www.plasma2002.com\/partyscroller\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"http:\/\/www.plasma2002.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Party Scroller"}]},{"@type":"WebSite","@id":"http:\/\/www.plasma2002.com\/blog\/#website","url":"http:\/\/www.plasma2002.com\/blog\/","name":"Plasma2002","description":"Ramblings from the Fourth State of Matter","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"http:\/\/www.plasma2002.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"http:\/\/www.plasma2002.com\/blog\/#\/schema\/person\/a99fb575da6efea98db3e249b5e3f108","name":"Plasma2002","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"http:\/\/www.plasma2002.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/cd4c32edd53cd00dd0feaf6d7abe80e169471f3c114539d040001015979afb5a?s=96&d=retro&r=r","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/cd4c32edd53cd00dd0feaf6d7abe80e169471f3c114539d040001015979afb5a?s=96&d=retro&r=r","caption":"Plasma2002"},"description":"For my bio, please see http:\/\/www.plasma2002.com\/about","sameAs":["http:\/\/www.plasma2002.com"],"url":"https:\/\/www.plasma2002.com\/blog\/author\/plasma2002\/"}]}},"_links":{"self":[{"href":"https:\/\/www.plasma2002.com\/blog\/wp-json\/wp\/v2\/posts\/459","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.plasma2002.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.plasma2002.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.plasma2002.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.plasma2002.com\/blog\/wp-json\/wp\/v2\/comments?post=459"}],"version-history":[{"count":8,"href":"https:\/\/www.plasma2002.com\/blog\/wp-json\/wp\/v2\/posts\/459\/revisions"}],"predecessor-version":[{"id":752,"href":"https:\/\/www.plasma2002.com\/blog\/wp-json\/wp\/v2\/posts\/459\/revisions\/752"}],"wp:attachment":[{"href":"https:\/\/www.plasma2002.com\/blog\/wp-json\/wp\/v2\/media?parent=459"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.plasma2002.com\/blog\/wp-json\/wp\/v2\/categories?post=459"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.plasma2002.com\/blog\/wp-json\/wp\/v2\/tags?post=459"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}