| Новости | 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[]]