Detect when song changes in Shoutcast server - php

I have a script that is reading the last line of a log file for my radio station using the following command.
watch -n 1 php script.php
That command above executes my script in 1 sec intervals. The log this script is reading has output as listed below.
2016-04-28 23:30:34 INFO [ADMINCGI sid=1] Title updated [Bankroll Fresh Feat. Street Money Boochie - Get It]
2016-04-28 23:30:34 INFO [ADMINCGI sid=1] DJ name updated [1]
2016-04-28 23:30:36 INFO [YP] Updating listing details for stream #1 succeeded.
Every time the song changes, 3 more lines are added to the logs as in the example output above. I need a way to do 3 things.
1) Detect only the latest occurrance of an entry in the logs matching the pattern of line #1
2) Execute code when that occurs and do nothing else until that happens again.
3) Regex to Extract data between 'second set' of square brackets on a line delimited by a "-" e.g. [Rihanna feat. Keyshia Cole - Title (Remix)]
Before the log output of my radio script changed, my script would detect when a song change occurred by tailing the logs for the 'Title Updated' line and then extract the artist and title name from within the square brackets on that same line.
Once that happens the data is sent to a MySQL database and sent to Twitter.
I have tried using "strpos" within an if statement to first detect a line that contains "Title updated" and then execute a function to grab the song information from the line afterwards which works but only if I use a static scenario by putting an example except of line #1 into a variable and then running it off my script. It does detect the line and server it's purpose but I need my script to remain dynamic meaning to only do something when this event happens and always sit idle in the meantime.
Right now I had to go bootleg and do the following.
Created a function to grab the last 3 lines from the log and then put each line into an array. Going off the example output above.
array[0] = Target Line
array[1] = next line
array[3] = next line
The logs would remain in this fashion as no other output is posted until the next song change and then it repeats with the only thing changing is the Artist and Title information. Currently since I am running my script to forcibly look at array[0] which is always the line I need, when it the script posts to Twitter on a song change, it immediately sends duplicates. Luckily I implemented error codes into the Twitter portion so that I can use sleep() to force my script to idle for 180 seconds (3 minutes) around the average song length. Now this is decent and it does post but my Tweets are no longer in real time because each song has different lengths.
Here is a snippet from my script below...
$lines = read_file(TEXT_FILE, LINES_COUNT);
foreach ($lines as $line) {
$pattern="/\[([^\]]*)\]/";
if (preg_match_all($pattern, $lines[0], $matches)){
foreach ($matches[1] as $a ){
$fulltitle = explode("-", $matches[1][1]);
$artist = $fulltitle[0];
$title = $fulltitle[1];
This script below is the direction I would like to go back to and does work when using the static version as in the example below. Soon as I set the script to look at the last line of the log it never detects a change due to it always detecting the next line after the target line. (believe regex may be responsible but not sure)
$line ="2016-04-27 22:56:48 INFO [ADMINCGI sid=1] Title updated [Tessa Feat. Gucci Mane - Get You Right]";
echo $line;
$pattern="/\[([^\]]*)\]/";
$needle = " Title updated ";
if (strpos($line,$needle) !== false) {
preg_match_all($pattern, $line, $matches);
foreach ($matches[1] as $a ){
$fulltitle = explode("-", $matches[1][1]);
$artist = $fulltitle[0];
$title = $fulltitle[1];

Related

Receiving cmd line arguments as array

Writing a little command-line script at the moment, and I've got it working pretty nicely.
The script loops until the user issues an exit command, during which the user can enter commands like so:
I 5 6
It denotes an image creation; 5 and 6 are the width and height to be created.
As it stands I can't seem to capture the user's input in an array. I can always get the first letter but never the other two with fgetc.
Currently capturing like this:
$input = strtolower(fgetc(STDIN));
Can somebody lend a hand?
fgetc() only reads in one character.
What you want to use is fgets().
In your case, to get an input line (in lowercase, as you apparently want it) as array, use:
$input_line = strtolower(fgets(STDIN));
$input_array = explode(" ", $input_line);
$input = explode(" ",strtolower(fgets(STDIN)));
fgetc() only reads one caracter, fgets() reads a string
Use fgets() to read the whole line.

Asterisk full log parser

I want to make a log parser for for an Asterisk PBX, but don't know where to start.
I figured it out what i need from the log. the lines that i need look like this:
[Apr 12 11:11:56] VERBOSE[3359] logger.c: -- Called 111
the number in VERBOSE[....] are the same for 1 call.
The first thing that i have to do is get the lines that contain that VERBOSE number so i can identify that call. the second thing is to read the text, there are some standard texts so it won't be hard to recognize.
The thing is that i would like to read it real time (the file is written real time), and display it in a webpage. PHP or Ajax.
The thing that i want to do is, show up rows in a webpage as users call. and the new call to be added under the current/answered call.
Any tips, examples would be great.
Thanks,
Sebastian
I would do it in 2 programs that can work as simple CGI programs.
First program parses log and show date and call identifier. Such identifier will be link to 2nd program. In Python you can use regexp:
# 1st group - date, 2nd - callid
RX_VERBOSE = re.compile(r'(.*) VERBOSE\[(\d+)\] ')
def make_link(call_id):
return(' <a href="show_call.cgi?call_id=%d>%d</a>' % (call_id, call_id))
def show_calls(logfn):
call_ids = []
f = open(logfn)
for line in f:
rx = RX_VERBOSE.search(line)
if rx:
call_id = int(rx.group(2))
if not call_id in call_ids:
print('%s %s' % (rx.group(1), make_link(call_id)))
call_ids.append(call_id)
f.close()
This program will show the lines that has call identifier:
def show_call_datails(logfn, call_id):
search_str = ' VERBOSE[%s] ' % call_id
f = open(logfn)
for line in f:
if search_str in line:
print(line.rstrip())
f.close()

change array number of defined string by increment - flat file database + ajax

I'm learning php. Novice. For that purpouse I decided to start with a flat file comment system.
I'm using ajax to post to php that writes data to a flat-file database.
Similar to: 12.01.2011¦¦the name¦¦the comment¦¦md5email¦¦0
Where '0' is the start number of comment 'likes'...thumbs-up.
Everything is working fine with ajax. Even the comment delete.
At page load jquery counts the comments (starting from 0) and assigns to each's comment-'like' an numbered id.
That number is than posted via ajax to php, resulting the file line number to modify.
That system works great for identifying the line to delete.
And it deletes the right line!
Now, having the line (or string?) number. How to:
Search the file for that line. (foreach...?!...)
Finded the line - split it into arrays. (Explode...?)
And increment by 1 the defined array value.
Limit maximum likes to 99.
(1 per user session).
Write file, close and so on.
- I just can't start count the 'like' clicks.
Please help.
Any ideas?
Thanks in advance!
$lines = file($filename, FILE_IGNORE_NEW_LINES);
$entry = explode('¦¦', $lines[$linenumber]);
$entry[4]++;
$lines[$lineNumber] = implode('¦¦', $entry);
file_put_contents($filename, implode("\n", $lines));

Pig's Stream Through PHP

I have a Pig script--currently running in local mode--that processes a huge file containing a list of categories:
/root/level1/level2/level3
/root/level1/level2/level3/level4
...
I need to insert each of these into an existing database by calling a stored procedure. Because I'm new to Pig and the UDF interface is a little daunting, I'm trying to get something done by streaming the file's content through a PHP script.
I'm finding that the PHP script only sees half of the category lines I'm passing through it, though. More precisely, I see a record returned for ceil( pig_categories/2 ). A limit of 15 will produce 8 entries after streaming through the PHP script--the last one will be empty.
-- Pig script snippet
ordered = ORDER mappable_categories BY category;
limited = LIMIT ordered 20;
categories = FOREACH limited GENERATE category;
DUMP categories; -- Displays all 20 categories
streamed = STREAM limited THROUGH `php -nF categorize.php`;
DUMP streamed; -- Displays 10 categories
# categorize.php
$category = fgets( STDIN );
echo $category;
Any thoughts on what I'm missing. I've poured over the Pig reference manual for a while now and there doesn't seem to be much information related to streaming through a PHP script. I've also tried the #hadoop channel on IRC to no avail. Any guidance would be much appreciated.
Thanks.
UPDATE
It's becoming evident that this is EOL-related. If I change the PHP script from using fgets() to stream_get_line(), then I get 10 items back, but the record that should be first is skipped and there's a trailing empty record that gets displayed.
(Arts/Animation)
(Arts/Animation/Anime)
(Arts/Animation/Anime/Characters)
(Arts/Animation/Anime/Clubs_and_Organizations)
(Arts/Animation/Anime/Collectibles)
(Arts/Animation/Anime/Collectibles/Cels)
(Arts/Animation/Anime/Collectibles/Models_and_Figures)
(Arts/Animation/Anime/Collectibles/Models_and_Figures/Action_Figures)
(Arts/Animation/Anime/Collectibles/Models_and_Figures/Action_Figures/Gundam)
()
In that result set, there should be a first item of (Arts). Closing in, but there's still some gap to close.
So it turns out that this is one of those instances where whitespace matters. I had an empty line in front of my opening <?php tag. Once I tightened all of that up, everything sailed through and produced as expected. /punitive headslap/

How can I tell what line a file resource is currently "on" in PHP?

Using PHP, it's possible to read off the contents of a file using fopen and fgets. Each time fgets is called, it returns the next line in the file.
How does fgets know what line to read? In other words, how does it know that it last read line 5, so it should return the contents of line 6 this time? Is there a way for me to access that line-number data?
(I know it's possible to do something similar by reading the entire contents of the file into an array with file, but I'd like to accomplish this with fopen.)
There is a "position" kept in memory for each file that is opened ; it is automatically updated each time you are reading a line/character/whatever from the file.
You can get this position with ftell, and modify it with fseek :
ftell — Returns the current position
of the file read/write pointer
fseek — Seeks on a file pointer
You can also use rewind to... rewind... the position of that pointer.
This is not getting you a position as a line number, but closer to a position as a character number (actually, you are getting the position as a number of bytes from the beginning of the file) ; when you have that, reading a line is just a metter of reading characters until yu hit an end of line character.
BTW : as far as I remember, these functions are coming from the C language -- PHP itself being written in C ;-)
Files are just a stream of data, read from the beginning to the end. The OS will remember the position you've read so far in that file. If needed, doing so in the application as well is fairly simple. The OS only cares about byte positions though, not lines.
Just imagine dealing out a deck of 52 card sequentially. You hand off the first card. Next time the 2. card. When you want to give out the 3. card , you don't need to start counting from the start again, or even remembering where you were you just hand out the next available card, and that'll be the third.
It might be a bit more work that's needed to read lines, since you'd want to buffer data read from the actual file for preformance sake, but it's not that much more to it than to record the offset of the last piece of data you handed out, find the next newline character and hand off all the data between those 2 points.
PHP nor the OS has no real need to keep the line number around, since all the system care about is "next line". If you want to know the line number, you keep a counter and increment it every time your app reads a line.
$lineno=0;
while (!feof($handle)) {
$buffer = fgets($handle, 4096);
lineno++; // keep track of the line number
...
}
i hav this old sample i hob its can help you :)
$File = file('path');
$array = array();
$linenr = 5;
foreach( $File AS $line_num => $line )
{
$array = array_push( $array , $line );
}
echo $array[($linenr-1)];
You could just call fgets and increment a var $line_number each time you call it. That would tell you the line it is on.

Categories