Command Line RSS Feed Monitor

By sunslayer on Mar 22, 2011

Watches a RSS feed and beeps when a change is discovered, defaults to check every 5 minutes

note: this must be run from the command line, not through your browser

<?php   
    class timer {

        public $callBack, $i, $t;

        public function __construct($i,$t,$w = 0) {
            $this->i = $i;
            $this->t = $t;
            if($i*$t > ini_get('max_execution_time') || $t < 1 && $w)
                trigger_error("max_execution_time will prevent timer from functioning completely", E_USER_WARNING);
        }

        public function add($cb,array $params=null) {
            if((@function_exists($cb)&&is_string($cb))||is_array($cb)&&count($cb)==2&&@method_exists($cb[0],$cb[1]))
                $this->callBack[] = array("f" => $cb, "p" => $params);
        }

        public function exec() {
            do {
                foreach($this->callBack as $cb) {
                    if(is_array($cb['f']))
                        $cb['f'] = implode("::",$cb['f']);
                    call_user_func_array($cb['f'],(array)$cb['p']);
                }
                $this->t--;
                sleep($this->i);
            }   while($this->t != 0);
        }

        public function __toString() {
            return __CLASS__;
        }
    }

    class Rss extends timer {
        public $lCache, $cCache, $tCache, $rss;

        public function __construct($rss,$i,$t) {
            parent::__construct($i,$t);
            $this->rss = $rss;
            $this->add(array($this,"getRss"),array($this->rss));
            echo "\nWatching:\t{$rss}\n\n";
            $this->exec();
        }

        public function getRss($url) {
            $this->cCache = $this->rssParser($url);
            if($this->lCache[0] != $this->cCache[0] && $this->lCache[0] != NULL) {
                $tCache = array();
                for($a = 0; $this->cCache[$a]; $a++)
                    if($this->cCache[$a]==$this->lCache[0])
                        break;
                for(;$a >= 0;$a--)
                    $tCache[] = $this->cCache[$a];
                unset($tCache[0]);
                $this->alert($tCache);
            }
            $this->lCache = $this->cCache;
            $this->cCache = array();
        }

        public function rssParser($url) {
            preg_match_all('/(?s)<item>(.+?)<\/item>/',file_get_contents($url),$rss);
            $array = array();
            foreach($rss[1] as &$rss) {
                preg_match_all('/(?s)<(title|description|link|pubDate|author)>(.+)<\/\1>/',$rss,$i);
                $item = array("title" => $i[2][0],"author" => $i[2][1],"link" => $i[2][2],"desc" => $i[2][3],"date" => $i[2][4]);
                array_push($array,$item);
            }
            return $array;
        }

        public function alert(array $cache) {
            echo "New posts detected! (".date('h:i:s A').")\n";
            foreach($cache as $t)
                echo "{$t['title']}\n";
            echo "\x07\x07\n";
        }

        public function __toString() {
            return __CLASS__;
        }
    }

    if ($argv[1])
        new Rss($argv[1],(is_int($argv[2])?$argv[2]:600),0);
?>

Comments

Sign in to comment.
dma   -  Dec 14, 2015

whats the commnad line???

 Respond  
Callumlord   -  Mar 27, 2011

Ah wait, I see thats for the ending. Lol sorry. My bad :)

 Respond  
Callumlord   -  Mar 27, 2011

oh Found a error:

} while($this->t != 0);
}

Added 2 }

 Respond  
Callumlord   -  Mar 27, 2011

Nice :P

 Respond  
Hawkee   -  Mar 24, 2011

Very good.

 Respond  
sunslayer   -  Mar 24, 2011

added

 Respond  
Hawkee   -  Mar 23, 2011

Very good, much better! The interval should be an optional command line value that defaults to 600.

 Respond  
sunslayer   -  Mar 23, 2011

yeah, i forgot to remove the asort() when i was testing. fixed. and to make it more dynamic(until i can figure out the control positioning) the url is passed through command line arguments

 Respond  
Hawkee   -  Mar 23, 2011

Also, it might be better to call this Command Line RSS Feed Monitor to get better placement in the search engines in order to get more traffic.

 Respond  
Hawkee   -  Mar 23, 2011

One problem I noticed was after it detects a new post it re-detects all the previous posts as new on the next round.

 Respond  
Hawkee   -  Mar 23, 2011

I finally got it working with a later version of PHP, but you might want to fix the sample URL, it's comment.rss.php, not comments. It's nice code overall.

 Respond  
Hawkee   -  Mar 23, 2011

I got this error without the toString function: "class 'timer' does not have a method 'getRss'" so I added it and this error went away.

 Respond  
sunslayer   -  Mar 23, 2011

it's inherited from the timer class, I'm also working on a GUI version of this but positioning the controls seems to be a bit tricky to get them where i want them

 Respond  
Hawkee   -  Mar 23, 2011

Aha, I suspected it might be a version specific error. You should put your toString fix in there.

 Respond  
sunslayer   -  Mar 23, 2011

Hawkee it seems to be a bug in that version as i get the same error when i run it on 5.2.6, it runs fine on 5.3.0

 Respond  
sunslayer   -  Mar 23, 2011

I've been debugging it for a while, it may be something on your end? unless anyone else is getting the same error
is your version configured for CLI? type "php -v" from the command prompt it should say PHP x.x.x (cli)

 Respond  
Hawkee   -  Mar 23, 2011

Any clues yet? I was looking into this and I couldn't find a solid answer.

 Respond  
Hawkee   -  Mar 22, 2011

Same problem except now it's telling me 'Rss::getRss' is not a valid callback. I'm running PHP 5.2.6.

 Respond  
sunslayer   -  Mar 22, 2011

ah, the toString method is in the timer class, try adding another __toString method to the Rss class

still doesn't make sense that it works for me though, what version of PHP are you using?

 Respond  
Hawkee   -  Mar 22, 2011

It returns false but method_exists('Rss','getRss') returns true. Probably has something to do with the class extending.

 Respond  
sunslayer   -  Mar 22, 2011

hmm, strange It works fine for me, what does method_exists('timer','getRss') return?

 Respond  
Hawkee   -  Mar 22, 2011

I just tried with the code that's currently here and I'm getting the same error.

 Respond  
sunslayer   -  Mar 22, 2011

@[Plornt] you will get a DOMDocument::load error

@Hawkee are you using the updated timer class?

 Respond  
Hawkee   -  Mar 22, 2011

I'm getting this error, PHP Warning: call_user_func_array(): First argument is expected to be a valid callback, 'timer::getRss' was given.

 Respond  
[Plornt]   -  Mar 22, 2011

http://php.net/manual/en/book.dom.php

That doesnt work in the command line :S?

Odd, im fairly sure it should?

 Respond  
sunslayer   -  Mar 22, 2011

edited, and yes it has to be run from the command line

 Respond  
Hawkee   -  Mar 22, 2011

Just for the sake of completeness you should probably include the timer here as well. Also, the call should be at the bottom after the class is defined.

 Respond  
Hawkee   -  Mar 22, 2011

So this is meant to be used from the command line?

 Respond  
sunslayer   -  Mar 22, 2011

@[Plornt] you can't access the DOM through the command line to run multiple you can run multiple processes i might add that later if this gets enough of a response

 Respond  
[Plornt]   -  Mar 22, 2011

Nice, I like et :)
Can it only do one RSS feed at a time?
Also I see you used regex, most php bundles have DOM stuff so you can read the feeds without the need for regex (Not sure on speed comparisons) but it could be nice to see that come out of the wood work!

 Respond  
Are you sure you want to unfollow this person?
Are you sure you want to delete this?
Click "Unsubscribe" to stop receiving notices pertaining to this post.
Click "Subscribe" to resume notices pertaining to this post.