Новости | FAQ | Авторы | Документация | В действии | Библиотека |
Инструменты | Полезные ссылки | Хостинги | Скачать | Примеры | Форум |
Sanja v.2 01.10.2003 11:27
Значит, родил я subj. Код ниже, пользуйтесь. Это кусок более масштабного проекта (знающие люди могут убедиться, что он продвигается).^rss:update_list[]вывод сообщений со всех подписанных сайтов в одну френдленту - так:
^rss:display[]Создайте две таблицы в MySQL, метод ^MAIN:dbconnect со строкой подключения в корневом auto.p и запишите туда же следующие переменные:
# URL сервера (без слэша на конце!) Обычно угадывается верно, но, например, # на хостинге Zenon это не всегда так, и приходится вписывать вручную): $global_server[$env:SERVER_NAME] # Сдвиг вашего локального времени (не летнего, обычного) от Гринвича # (в Лондоне - 12:00, в Москве - 15:00, получается, что $global_timeoffset = +3 ) # (Для жителей центральной Австралии - ваш offset - дробный: "9.5") $global_timeoffset(3) # Ваше локальное время сдвигается летом? $global_daylight[yes] # Это происходит с [день, месяц] по [день, месяц]: # (обычно с 29-Mar по 25-Oct, см. http://www.worldtimezone.com/daylight.htm) $global_daylight_m_start(3) $global_daylight_d_start(29) $global_daylight_m_end(10) $global_daylight_d_end(25)SQL Dump
# # Table structure for table 'cityblog_rssitems' # DROP TABLE IF EXISTS cityblog_rssitems; CREATE TABLE cityblog_rssitems ( id int(16) unsigned NOT NULL auto_increment, title text, link varchar(255) NOT NULL default '/', description text NOT NULL, pubdate datetime NOT NULL default '0000-00-00 00:00:00', PRIMARY KEY (id), UNIQUE KEY id (id), KEY id_2 (id) ) TYPE=MyISAM COMMENT='Items from RSS feeds'; # # Table structure for table 'cityblog_rsslist' # DROP TABLE IF EXISTS cityblog_rsslist; CREATE TABLE cityblog_rsslist ( uri varchar(255) NOT NULL default '', name varchar(255) default NULL, last_update datetime NOT NULL default '0000-00-00 00:00:00', is_enabled enum('yes','no') NOT NULL default 'no', min_refresh_period tinyint(3) unsigned NOT NULL default '1', hours_to_keep tinyint(3) unsigned NOT NULL default '24', PRIMARY KEY (uri), UNIQUE KEY uri (uri), KEY uri_2 (uri) ) TYPE=MyISAM COMMENT='RSS feeds to fetch'; # # Dumping data for table 'cityblog_rsslist' # INSERT INTO cityblog_rsslist (uri, name, last_update, is_enabled, min_refresh_period, hours_to_keep) VALUES("http://forum.gfk.ru/forum/rss.html", "Forum.GfK.ru", "2003-10-01 11:15:41", "yes", "1", "24"); INSERT INTO cityblog_rsslist (uri, name, last_update, is_enabled, min_refresh_period, hours_to_keep) VALUES("http://www.parser.ru/_rss.html", "Parser.ru Forum", "0000-00-00 00:00:00", "no", "1", "24");Файлы классов: rss.p
############################## # В этот класс вынесен весь код, который # отвечает за чтение RSS потоков с других сайтов. @CLASS rss @USE log.p ############################## # Загрузчик @load[] $result[] ############################## # Получение списка RSS ньюсфидов, которые не обновлялись больше часов, чем # указано в столбце min_refresh_period и их обновление @update_list[] <p>Идёт поиск RSS-лент, которые должны быть обновлены…^; ^MAIN:dbconnect{ $rss_feeds[ ^table::sql{SELECT uri, name, last_update, is_enabled, min_refresh_period, hours_to_keep FROM cityblog_rsslist WHERE is_enabled="yes" AND (UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(last_update)) >= (min_refresh_period * 60 * 60) # В часе 60 минут по 60 секунд, если вы не в курсе :-) ORDER BY last_update } ] ^if(def $rss_feeds){ <ul> ^rss_feeds.menu{ <li><a href="$rss_feeds.uri" target="_new">$rss_feeds.name</a> последний раз был открыт $rss_feeds.last_update, выполняется обновление…^;</li> ^update_feed[$rss_feeds.uri] ^void:sql{DELETE FROM cityblog_rssitems WHERE (UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(pubdate)) >= ($rss_feeds.hours_to_keep * 60 * 60) AND link = "$rss_feeds.uri" } } </ul> }{ <p>В настоящий момент таковых нет.</p> } } ############################## # Повторное чтение RSS потока, разбор и запись в базу обновлений: @update_feed[feeduri] # пытаемся загрузить RSS файл с помощью ^file::load # При этом может произойти целая туча неприятностей - другой сервер может не отвечать, # файл окажется испорчен или удалён - на этот случай мы пользуемся оператором ^try ^try{ # Считаем, что RSS-поток пришёл в кодировке $rss[^file::load[text;^untaint{$feeduri}; $.timeout(5) $.headers[ $.User-Agent[CityBlog RSS aggregator from $MAIN:$global_server] ] ]] $xml[^xdoc::create{^untaint{$rss.text}}] $items[^xml.select[/rss/channel/item]] }{ $exception.handled(1) $result[ Не получилось загрузить RSS-поток!] ^log:write[Не получилось загрузить RSS-поток $feeduri] } $updatedcnt(0) ^if(def $items){ <h1>$Encoding</h1> # Нам нужно узнать версию RSS-потока, который мы получили. # Тонкость в том, что у RSS 2.0 есть тэг PubDate, а у RSS 0.91 нету. # Поэтому для RSS 2 мы пользуемся тем, что есть, а для старых версий RSS # пользуемся политикой "дата, когда выкачали = дата создания" $rss_version[^xml.selectString[string(rss/@version)]] ^for[i](1;$items){ ^if($rss_version eq "2.0"){ $date{^xml.selectString[string(/rss/channel/item[position() = $i]/pubDate)]} # Вы думали, чехарда с датами закончилась? А нифига ;-) # Дата может быть в таком формате - Tue, 30 Sep 2003 14:32:46 MSD # или в таком - Mon, 29 Sep 2003 11:23:12 GMT. A есть ещё обозначение "UTC"... # see also: http://208.30.42.17/logistics/tzhelp.asp # http://www.worldtimezone.com/wtz-names/wtz-msks.html # Нам надо привести это время к нашему локальному $date[^date::create[^dates:string2GMT[$date]]] }{ # Если мы имеем дело с RSS старой версии, берём текущую дату, приведённую к Гринвичу: $date[^date::create[^dates:GMT_datetime[]]] } $title{^xml.selectString[string(/rss/channel/item[position() = $i]/title)]} $link{^xml.selectString[string(/rss/channel/item[position() = $i]/link)]} $description{^xml.selectString[string(/rss/channel/item[position() = $i]/description)]} $countitems[^table::sql{SELECT COUNT(*) AS cnt FROM cityblog_rssitems WHERE link = "$link" }] $counter[$countitems.cnt] $counter(^counter.int(1)) ^if($counter == 0){ ^void:sql{INSERT INTO cityblog_rssitems (title,link,description,pubdate) VALUES ("$title", "$link", "$description", "^date.sql-string[]") } }{ # Эта запись уже выкачивалась, апдейтить не надо. } # <p><a href="$link">$title</a> (^date.sql-string[])</p> ^updatedcnt.inc[] } # Обновляем запись об этом RSS-фиде в базе: ^void:sql{UPDATE cityblog_rsslist SET last_update = NOW() WHERE uri = "$feeduri" } } Найдено новых записей: $updatedcnt </p> @display[] ^MAIN:dbconnect{ $rss_items[ ^table::sql{SELECT id, title, link, description, DATE_FORMAT(pubdate, "%d/%m/%Y, %H:%i") as date FROM cityblog_rssitems ORDER BY pubdate DESC} ] } ^if(def $rss_items){ <ul> ^rss_items.menu{ <li><a href="$rss_items.link">$rss_items.title</a> ($rss_items.date GMT)</li> } </ul> }Файлы классов: dates.p
############################## # Класс для работы с датами @CLASS dates ############################## # Получаем текущую дату по Гринвичу из нашей локальной: @load[] # Нам нужно узнать, на сколько сдвинуть текущую дату и время. # Сдвиг складывается из разницы по отношению к Гринвичу + поправки на летнее время $local[^date::now[]] # Летнее время: ^if($MAIN:global_daylight eq "yes"){ # Попадает ли текущая дата в промежуток, когда вводится летнее время? $daylight_lbound[^date::create($local.year;$MAIN:global_daylight_m_start;$MAIN:global_daylight_d_start;0;0;0)] $daylight_ubound[^date::create($local.year;$MAIN:global_daylight_m_end;$MAIN:global_daylight_d_end;0;0;0)] ^if( ($local.day >= $daylight_lbound.day) && ($local.month >= $daylight_lbound.month) && ($local.day <= $daylight_ubound.day) && ($local.month <= $daylight_ubound.month) ){ # Текущая дата - в том, диапазоне, в котором летнее время в силе: $daylight_offset(1) }{ # ...или нет: $daylight_offset(0) } } # Из текущей даты и времени мы должны вычесть час летнего времени и разницу с Гринвичем: $GMTdate[^date::create($local - (($daylight_offset + $MAIN:global_timeoffset)/24))] ############################## # Получаем текущую дату (системную): @local_datetime[] $result[^local.sql-string[]] ############################## # Получаем текущую дату (приведённую к Гринвичу): @GMT_datetime[] $result[^GMTdate.sql-string[]] ############################## # Приводим дату в виде строки ("Mon, 29 Sep 2003 11:23:12 GMT") к Гринвичу: @string2GMT[string] ^string.match[([A-Za-z]{3}), ([0-9]+) ([A-Za-z]{3}) ([0-9]+) ([0-9]+):([0-9]+):([0-9]+) ([A-Za-z]{3,4})][g]{ $year($match.4) $month[$match.3] ^if($month eq Jan){$month(1)} ^if($month eq Feb){$month(2)} ^if($month eq Mar){$month(3)} ^if($month eq Apr){$month(4)} ^if($month eq May){$month(5)} ^if($month eq Jun){$month(6)} ^if($month eq Jul){$month(7)} ^if($month eq Aug){$month(8)} ^if($month eq Sep){$month(9)} ^if($month eq Oct){$month(10)} ^if($month eq Nov){$month(11)} ^if($month eq Dec){$month(12)} $day($match.2) $hour($match.5) $minute($match.6) $second($match.7) $timezonename[$match.8] } # Табличка с названиями временных зон и поправками: # Название Аббр. Поправка # Samoa Standard Time SST -11 # Hawaii-Aleutian Standard Time HST -10 # Alaska Standard Time AKST -9 # Hawaii-Aleutian Daylight Time HDT -9 # Alaska Daylight Time AKDT -8 # Pacific Standard Time PST -8 # Mountain Standard Time MST -7 # Pacific Daylight Time PDT -7 # Central Standard Time CST -6 # Mountain Daylight Time MDT -6 # Central Daylight Time CDT -5 # Eastern Standard Time EST -5 # Atlantic Standard Time AST -4 # Eastern Daylight Time EDT -4 # Atlantic Daylight Time ADT -3 # Greenwich Mean Time GMT 0 # Western Europe Time WET 0 # British Summer Time BST 1 # Central Europe Time CET 1 # Irish Summer Time IST 1 # Western Europe Summer Time WEST 1 # Central Europe Summer Time CEST 2 # Eastern Europe Time EET 2 # Eastern Europe Summer Time EEST 3 # Moscow Time MSK 3 # Moscow Summer Time MSD 4 # Western Standard Time WST 8 # Central Standard Time CST 9.5 # Eastern Standard Time EST 10 ^if(def $year && def $month && def $day){ ^switch[$timezonename]{ ^case[SST]{$tz_offset(-11)} ^case[HST]{$tz_offset(-10)} ^case[AKST]{$tz_offset(-9)} ^case[HDT]{$tz_offset(-9)} ^case[AKDT]{$tz_offset(-8)} ^case[PST]{$tz_offset(-8)} ^case[MST]{$tz_offset(-7)} ^case[PDT]{$tz_offset(-7)} ^case[CST]{$tz_offset(-6)} ^case[MDT]{$tz_offset(-6)} ^case[CDT]{$tz_offset(-5)} ^case[EST]{$tz_offset(-5)} ^case[AST]{$tz_offset(-4)} ^case[EDT]{$tz_offset(-4)} ^case[ADT]{$tz_offset(-3)} ^case[GMT]{$tz_offset(0)} ^case[WET]{$tz_offset(0)} ^case[BST]{$tz_offset(1)} ^case[CET]{$tz_offset(1)} ^case[IST]{$tz_offset(1)} ^case[WEST]{$tz_offset(1)} ^case[CEST]{$tz_offset(2)} ^case[EET]{$tz_offset(2)} ^case[EEST]{$tz_offset(3)} ^case[MSK]{$tz_offset(3)} ^case[MSD]{$tz_offset(4)} ^case[WST]{$tz_offset(8)} ^case[CST]{$tz_offset(9.5)} ^case[EST]{$tz_offset(10)} ^case[DEFAULT]{$tz_offset(0)} } $UnadjustedString[^date::create($year;$month;$day;$hour;$minute;$second)] $GMTString[^date::create($UnadjustedString - ($tz_offset/24))] }{ $GMTString[^date::now[]] } $result[^GMTString.sql-string[]]