// Var 21.12.2014
int mpiFolderType = 200;
int mpiDynamicScript = 500;
int mpiDynamicSyntaxType = 501;
int mpiPreviousItemID = 200104;
int mpiDoNothing = 201100;
char gsSpace = 'Пробел';
char gsDelLastChar = 'Удалить последний символ';
char gsClearSearch = 'Очистить текст поиска';
char gsClearHystoryIn = 'Очистить историю поиска в папке "%s"';
char gsMsgClearHistory = 'История поиска в папке "%s" очищена';
char gsMsgTextSaved = 'Подкаст "%s" добавлен в "%s"';
char gsMsgNothingSaved = 'Текст поиска не набран! Добавлять нечего.';
char gsMsgSearchText = 'Текст поиска: %s';
char gsAddSearchTo = 'Добавить в папку "%s"';
char gsSuggestQuery = 'http://www.google.ru/complete/search?sclient=psy-ab&q=';
char gsSuggestResultCut= '';
char gsSuggestRegExpr = '\\["(.*?)",';
char gsSuggestMethod = 'GET';
int gnSuggestNoUTFEnc = 0;
char gsSuggestMessage = 'Вариант: ';
int gnTotalItems=0; TDateTime gTimeStart = Now; char gsTextSearch, gsMsg='';
THmsScriptMediaItem goRootItem, goCmdItem;
// ------------------------------------------ Создание папок команд поиска ----
void CreateSearchCommands() {
int i; char sText; THmsScriptMediaItem Item;
CreateDynamicItem(FolderItem, '#', '-SearchCreateChars=From:32To:58');
CreateDynamicItem(FolderItem, 'A-Z', '-SearchCreateChars=From:65To:91');
CreateDynamicItem(FolderItem, 'А-Я', '-SearchCreateChars=From:192To:224');
CreateDynamicItem(FolderItem, gsClearSearch, '-SearchCmd=ClearSearchText');
// Создание команды добавления в корневую папку поиска
CreateDynamicItem(FolderItem, Format(gsAddSearchTo, [goRootItem[mpiTitle]]), '-SearchCmd=SaveSearchText');
// Создание команд добавления в папки, находящиеся в корневой, если поле "Файл" (mpiFilePath) у них пустое
for (i=0; i<goRootItem.ChildCount; i++) {
Item = goRootItem.ChildItems[i];
if (Item.ItemClassID!=51) continue;
CreateDynamicItem(FolderItem, Format(gsAddSearchTo, [Item[mpiTitle]]), '-SaveSearchTextTo='+Item.ItemID);
}
// Создание команды очистки истории в корневой папке поиска
CreateDynamicItem(FolderItem, Format(gsClearHystoryIn, [goRootItem[mpiTitle]]), '-SearchCmd=ClearSearchHistory');
// Создание команд очистки истории в папках, которые наодятся в корневой
for (i=0; i<goRootItem.ChildCount; i++) {
Item = goRootItem.ChildItems[i];
if (Item.ItemClassID!=51) continue;
CreateDynamicItem(FolderItem, Format(gsClearHystoryIn, [Item[mpiTitle]]), '-ClearSearchHistoryIn='+Item.ItemID);
}
// Создание ссылки, информирующей о текущем набранном тексте поиска
sText = Format(gsMsgSearchText, [gsTextSearch]);
Item = HmsCreateMediaItem(sText, goCmdItem.ItemID);
Item[mpiTitle ] = sText;
Item[mpiThumbnail] = 'http://wonky.lostcut.net/icons/search-icon1.jpg';
}
// ---------------------------- Добавление подкаста с именем текста поиска ----
void AddPodcastSearch(THmsScriptMediaItem prntItem) {
THmsScriptMediaItem Item;
if (Trim(gsTextSearch)=='') {gsMsg = gsMsgNothingSaved; return;}
if (LowerCase(gsTextSearch)==gsTextSearch) gsTextSearch = NameCase(gsTextSearch);
Item = prntItem.AddFolder(gsTextSearch, false);
Item[mpiFilePath ] = Format('search="%s"', [gsTextSearch]);
Item[mpiTitle ] = gsTextSearch;
HmsDatabaseAutoSave(false);
gsMsg = Format(gsMsgTextSaved, [gsTextSearch, prntItem[mpiTitle]]);
//gsTextSearch = '';
}
// --------- Функция создания динамической папки с унаследованным скриптом ----
void CreateDynamicItem(THmsScriptMediaItem prntItem, char sTitle, char sLink) {
char s; THmsScriptMediaItem Folder;
if (Trim(sTitle)=='') sTitle = gsSpace;
Folder = prntItem.AddFolder(sLink, true);
Folder[mpiTitle ] = sTitle;
Folder[mpiCreateDate ] = VarToStr(IncTime(gTimeStart,0,-gnTotalItems,0,0)); gnTotalItems++;
Folder[mpiFolderType ] = prntItem[mpiFolderType];
Folder[mpiDynamicScript ] = prntItem[mpiDynamicScript];
Folder[mpiDynamicSyntaxType] = prntItem[mpiDynamicSyntaxType];
Folder[mpiFolderSortOrder ] = prntItem[mpiFolderSortOrder];
}
// ---------------------------- MAIN PROCEDURE ------------------------------
{
int i, nCnt; char sCh, sCh1, sCh2, sText; THmsScriptMediaItem Item;
char s, sUrlServer = '', sRequestPage = '/', sPostData = '', sHeaders = '';
if (LeftCopy(mpFilePath, 1) != '-') return; // Если это не команда - то и не обрабатываем
// Поиск корневого каталога поиска (папки, которая содержит динамическую папку с путем "-SearchCommands")
goRootItem = FolderItem; goCmdItem = FolderItem;
while ((goRootItem.ItemParent != HmsDatabaseRootItem) && (goRootItem.ItemParent != nil)) {
if (goRootItem[mpiFilePath] == '-SearchCommands') {goCmdItem=goRootItem; goRootItem=goCmdItem.ItemParent; break;}
goRootItem = goRootItem.ItemParent;
}
// Если это повторный вызов, смены папки не произошло - ничего не делаем
if ((FolderItem.ItemID==goRootItem[mpiPreviousItemID]) && !DebugMode && (FolderItem!=goCmdItem)) return;
FolderItem.DeleteChildItems(); goRootItem[mpiPreviousItemID] = FolderItem.ItemID;
gsTextSearch = HmsGetUserSearchText(); // Получаем текущее значение текста поиска
// ---- Проверяем команды - по значению в mpFilePath ----
if (goRootItem[mpiDoNothing]=='1') { // Флаг "Ничего не делать" - например, при возврате
goRootItem[mpiDoNothing] = ''; // в команду набирания буквы из подпапки варианта
} else if (HmsRegExMatch('-SearchCommands', mpFilePath, sCh1)) { // Создание корневых команд поиска
CreateSearchCommands(); return;
} else if (HmsRegExMatch('-SearchChar=(\\d+)', mpFilePath, sCh1)) { // Добавление буквы (символа) к набираемому тексту поиска
gsTextSearch += Chr(StrToInt(sCh1));
} else if (HmsRegExMatch('-SetSearchText=(.*)', mpFilePath, gsTextSearch)) { // Назначить текст поиска значением варианта подсказки
goRootItem[mpiDoNothing] = '1'; gsSuggestQuery = ''; // включаем флаг не выполнять команду при возврате из этой папки
} else if (HmsRegExMatch('-SaveSearchTextTo=(.*)', mpFilePath, sCh1)) { // Добавление в папку Х. Поиск этой папки по ItemID.
Item = goRootItem; // Ищем папку с ItemID равному идентификатору, переданному в mpFilePath
for (i=0; i<goRootItem.ChildCount; i++) {
if (goRootItem.ChildItems[i].ItemID==sCh1) {Item = goRootItem.ChildItems[i]; break;}
}
AddPodcastSearch(Item); // и добавляем в найденную папку подкаст текстом поиска
} else if (HmsRegExMatch('-ClearSearchHistoryIn=(.*)', mpFilePath, sCh1)) { // Очистка истории (добавленных ранее) поисковых значений
Item = goRootItem; // Ищем папку с ItemID равному идентификатору, переданному в mpFilePath
for (i=0; i<goRootItem.ChildCount; i++) {
if (goRootItem.ChildItems[i].ItemID==sCh1) {Item = goRootItem.ChildItems[i]; break;}
}
for(i=0; i<Item.ChildCount; i++) { // Удаляем все элементы с начинающимся словом 'search' в поле mpiFilePath
if (LeftCopy(Item.ChildItems[i].Properties[mpiFilePath], 6)=='search') {Item.ChildItems[i].Delete();i--;}
}
gsMsg = Format(gsMsgClearHistory, [Item[mpiTitle]]); // вывод сообщения, что история очищена
} else if (HmsRegExMatch('-SearchCmd=(\\w+)', mpFilePath, sCh1)) {
if (sCh1=='DeleteLastChar' ) gsTextSearch = LeftCopy(gsTextSearch, Length(gsTextSearch)-1); // Удаление последнего символа
else if (sCh1=='SaveSearchText' ) AddPodcastSearch(goRootItem); // Добавить текст поиска в корневую папку
else if (sCh1=='ClearSearchText') gsTextSearch = ''; // Очистка текста поиска
else if (sCh1=='ClearSearchHistory') { // Очистка истории (добавленных значений поиска)
for(i=0; i<goRootItem.ChildCount; i++) {
Item = goRootItem.ChildItems[i]; // Ищем все элементы, у которых значение mpiFilePath начиначется с 'search'
if (LeftCopy(Item[mpiFilePath], 6)=='search') {goRootItem.ChildItems[i].Delete();i--;}
}
gsMsg = Format(gsMsgClearHistory, [goRootItem[mpiTitle]]);
}
} else if (HmsRegExMatch2('-SearchCreateChars=From:(\\d+)To:(\\d+)', mpFilePath, sCh1, sCh2)) { // Создание списка букв/символов
CreateDynamicItem(FolderItem, gsDelLastChar, '-SearchCmd=DeleteLastChar Suggestions'); // В начало - команда удаления символа
CreateDynamicItem(FolderItem, ' ', '-SearchChar=32 Suggestions'); // Пробел
for (i= StrToInt(sCh1); i<StrToInt(sCh2); i++) CreateDynamicItem(FolderItem, Chr(i), '-SearchChar='+IntToStr(i)+' Suggestions');
// слово "Suggestions" добавлено к значению mpiFilePath тек команд, в которых возможно использование подсказок
}
else return; // Если неизвестная нам команда - просто выходим
HmsSetUserSearchText(gsTextSearch); // Устанавливаем значение текста поиска
Item = HmsCreateMediaItem('-command=none', FolderItem.ItemID);
if (gsMsg=='') { // Если сообщения небыло - просто выводим ссылку с текущим значением набранного текста
Item[mpiThumbnail] = 'http://wonky.lostcut.net/icons/search-icon1.jpg';
Item[mpiFilePath ] = Format(gsMsgSearchText, [gsTextSearch]);
} else { // Выводим сообщение
Item[mpiThumbnail] = 'http://wonky.lostcut.net/icons/ok.png';
Item[mpiFilePath ] = gsMsg;
}
Item = HmsCreateMediaItem('-command=none', FolderItem.ItemParent.ItemID); // В родительской папке (выше) обновляем информацию о текущем значении текста
Item[mpiFilePath] = Format(gsMsgSearchText, [gsTextSearch]);
Item[mpiThumbnail] = 'http://wonky.lostcut.net/icons/search-icon1.jpg';
Item = HmsCreateMediaItem('-command=none', goCmdItem.ItemID); // Также в папке, содержащую главные команды поиска
Item[mpiFilePath] = Format(gsMsgSearchText, [gsTextSearch]);
Item[mpiThumbnail] = 'http://wonky.lostcut.net/icons/search-icon1.jpg';
// Suggestions ------ Блок работы с подсказками -------
if ((gsSuggestQuery!='') && (Pos('Suggestions', mpFilePath)>0) && (Length(gsTextSearch)>1)) {
sText = gsTextSearch; if (gnSuggestNoUTFEnc==0) sText = HmsUtf8Encode(sText); // Если не указано не кодировать в UTF - кодируем
sText = HmsHttpEncode(sText);
// Если есть ключ <TEXT> в запросе - заменяем его на значение набранного текста, иначе просто добавляем в конец
if (Pos('<TEXT>', gsSuggestQuery)>0) gsSuggestQuery = ReplaceStr(gsSuggestQuery, '<TEXT>', sText);
else gsSuggestQuery = gsSuggestQuery + sText;
HmsRegExMatch2('https?://(.*?)(/.*)', gsSuggestQuery, sUrlServer, sRequestPage);
if (gsSuggestMethod=='POST') HmsRegExMatch2('^(.*?)\\?(.*)', sRequestPage, sRequestPage, sPostData);
sHeaders = 'http://'+sUrlServer+'/\r\n'+
'Accept-Encoding: gzip, deflate\r\n'+
'User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:13.0) Gecko/20100101 Firefox/13.0\r\n'+
'Connection: Keep-Alive\r\n'+
'Accept: application/json, text/javascript, */*; q=0.01\r\n'; // Для включения возможности gzip в запросах
sText = HmsSendRequestEx(sUrlServer, sRequestPage, gsSuggestMethod, 'application/x-www-form-urlencoded; Charset=UTF-8', sHeaders, sPostData, 80, 0, '', true);
sText = HmsUtf8Decode(sText);
if (gsSuggestResultCut!='') HmsRegExMatch(gsSuggestResultCut, sText, sText);// Если есть выражение обрезки - обрезаем
sText = HmsJsonDecode(sText); TRegExpr t = TRegExpr.Create('(<[^>]+>)'); // Избавляемся от тегов в середине слов подсказки
TRegExpr reSearch = TRegExpr.Create(gsSuggestRegExpr, PCRE_SINGLELINE);
if (reSearch.Search(sText)) do {
s = reSearch.Match;
if (t.Search(s)) do s=ReplaceStr(s, t.Match, ''); while (t.SearchAgain());// (функция HmsHtmlToText не подходит т.к. ставит пробел в середине слова)
if (HmsRegExMatch('^(.*?)[/\\(\\|]', s, sCh)) { // Обрезаем подсказку до знаков /, ( или |
if (Pos(LowerCase(gsTextSearch), LowerCase(sCh))>0) s = sCh; // Если после этого в подсказке встречается набранный текст - то так и оставляем
}
if (LowerCase(s)==s) s = NameCase(s); // Если подсказки - все маленькие буквы, делаем NameCase
// Если в подсказке больше одного слова - дополнительно создаём сначала подсказки из слов, которые содержат набранный текст (выделяем слова отдельно)
if (WordCount(s, ' ')>1) {
nCnt = WordCount(s, ' ');
for (i=1; i<=nCnt; i++) {
sCh=ExtractWord(i, s, ' '); if (Trim(sCh)=='') continue;
if (Pos(LowerCase(gsTextSearch), LowerCase(sCh))<1) continue;
if (LowerCase(gsTextSearch)==LowerCase(sCh)) continue;
sCh = ReplaceStr(sCh, ':', ''); sCh=ReplaceStr(sCh, '\\', '');
CreateDynamicItem(FolderItem, gsSuggestMessage+sCh, '-SetSearchText='+sCh);
}
}
// Создаём папку с предложением варианта (подсказку)
if (LowerCase(s)!=LowerCase(gsTextSearch)) CreateDynamicItem(FolderItem, gsSuggestMessage+s, '-SetSearchText='+s);
if (gnTotalItems>100) break; // Ограничиваем количество создаваемых элементов = 100
} while (reSearch.SearchAgain());
}
HmsIncSystemUpdateID(); // Говорим устройству об обновлении содержания
}