- Регистрация
- 01.05.2014
- Сообщения
- 228
- Благодарностей
- 220
- Баллы
- 43
Всем привет, хоть я сейчас и загружен очень сильно на проекте по телеграм, да еще и сопли по колено, нашел таки время отписать коротенькую статейку по поводу защиты своих шаблонов.
Интро:
Весь код, который тут представлен, написан на C# за исключением скриптов гугл ). Тем кто не разбирается в Шарпе, рекомендую уделить время по изучать его, ну или использовать готовое решение в своих целях. Я сам так часто поступаю .
Интро2:
Сидел писал статью и на Складчике пришло уведомление, что появился новый ответ в отслеживаемой теме, как оказалось апнули довольно старую тему по защите шаблонов от уважаемого @Moadip, оценив его идею и свои наработки пришел к выводу, что скорее всего он меня натолкнул на этот краеугольный камень ))). Отмечу что наши идеи схожи, но реализации разные.
Стартуем:
Итак, с чего начнем - для тех кто не знает, шаблоны можно зашифровать и установить в них права стандартным модулем zennoposter "Шифрование"
Казалось бы этого достаточно, но не тут то было )) многие, кто оказывает услуги по разработке шаблонов, сталкивались с нерадивыми заказчиками, которые получали решение, а оплачивать отказывались; пару топиков тут уже проскакивали с гневом шаблонописцев. Что делать? Можно воспользоваться личным кабинетом, разделом боты и не заморачиваться для тех кто не в курсе смотреть сюда https://userarea.zennolab.com/lk/login.aspx
- Ну вот теперь та проблема решена же!
Да, можно и так защитить свой труд, но ведь все мы ушлые ребятки и не хотим морозить 10-20-100 баксов на счету в ЛК ЗенноЛаба (@nuaru ни чего личного . Я просто хочу рассказать, что делаю сам и ни в коей мере не призываю отказаться от выписки шаблонов через ЛК! )
А мы с вами тем временем пойдем по другому пути. Итак, давайте создадим пустой проект и накидаем в него пару кубиков , ну 3 если быть точным.
Думаю тут нет вопросов ни у кого...
Идем далее, давайте подумаем как бы нам защищаться, та?
Самый очевидный путь собрать какие то данные из окружения зенки и/или ПК и что-то с ними сделать.
На ум приходит сразу то, что зенка привязана к e-mail, который не меняется. Давайте его и будем использовать.
А как нам его получить? Да очень просто:
Да все верно, выдираем из реестра почту привязанную к зенке!
Думаем дальше:
Хочу, чтобы я мог ограничивать работу шаблона в каком то периоде: часы, дни, годы. Ну и отлично Значит, нам нужно сохранять дату каким-то образом.
О! Забыли подумать над тем, что на каждом компе время может отличаться(разные часовые пояса), ну для этого у наст есть стандартизация времени по-Гринвичу и, чтобы получить текущую дату по Гринвичу, нужно выполнить такой код:
Почитайте те, кто не знаком с классом DateTime https://msdn.microsoft.com/ru-ru/library/k494fzbf(v=vs.100).aspx - узнаете много интересного!
Отличненько, что далее?
Теперь нам нужно каким-то образом где-то проверить, а может шаблон работать или нет. Другими словами, нам нужно где-то что-то посмотреть и узнать, что шаблон может запускаться.
Ну, так давайте уже знакомиться с сервисом google script app!
Сперва создадим пустую гугл табличку и посмотрим на вкладку инструменты:
Конечно же тыкайте на "Редактор скриптов", я думал вы уже тыкнули . Главное потом нажмите сюда
У вас, скорее всего, там будет пусто, а у меня уже есть пару боевых скриптов.
Полагаю, что вы же ткнули "Создание проекта" и увидели вот такую картинку:
стираем там все, что написано и пишем код:
Как вы уже заметили, тут две функции: пустых, которые обрабатывают различные события, соответственно doGet - обрабатывает гет запросы к нашему скрипту, а doPost - пост запросы.
Что дальше? А давайте исправим doGet так, чтобы он нам возвращал те данные, которые мы ему передали. Исправьте скрипт следующим образом:
Немного пояснений:
Как вы видите из кода, функция doGet принимает один объект - e, который содержит в себе все параметры, переданные запросом в УРЛ. В нашем случае использовано 2 параметра mail и date.
Ну вот, пришла пора выставить скрипт наружу. Для этого сделаем следующее:
Нажмем на кнопку.
Теперь выполним следующие действия:
Версия: новый
Как запускать: От моего имени
Кто имеет доступ: Все, включая анонимных
И, нажимаем "Развернуть", после чего гугл попросит нас подтвердить разрешение на внесение изменений, мы, конечно же, соглашаемся! А может и не попросит У меня перестал просить, наверное от того, что я все скрипты храню в одной таблице.
Копируем урл скрипта. Он появится в отдельном окошке, но если вы забыли его скопировать, то нажмите "Публикация" - "Развернуть как веб приложение" и вверху увидите заветный УРЛ скрипта.
ВАЖНО! Если вы внесли какие-то изменения в скрипт, то вам нужно провести процедуру публикации и указать версию "НОВЫЙ".
Для тех, кто любит читать по Англицки, кидаю фулдок по веб АПП https://developers.google.com/apps-script/guides/web
Урл скопировали, давайте вернемся к шаблону.
В кубик C# добавим такой код, запустим его на выполнение и посмотрим, что получили:
Вставили? Запустили? Получили свой емаил и текущую дату?
Отлично! Двигаемся далее.
Действиями выше, мы связали зенку с GAS. Теперь, давайте думать, что у нас будет в бэкэнде - содержание гугл таблички.
Очевидно, что в табличке мы должны хранить электронный адрес клиента, дату, до которой он может пользоваться шаблоном, а так же название шаблона. Вот такую табличку давайте и сделаем.
Как вы видите на скрине, я добавил еще одно поле - "HASH". А зачем спросите вы? Так будет проще искать нужную строчку в таблице. Т.е. вместо того, чтобы делать два запроса к таблице (Сначала найдем все строки по полю Client, а потом из этих строк будем искать TemplateName), мы будем искать по одному полю под названием "HASH", а значение этого поля будет рассчитано таким образом:
То бишь соединим строковое значения емайл адреса клиента и название шаблона, и возьмем хэш от полученной строки!
ОК! Теперь давайте научим наш гугло скрипт искать данные в таблице, а для этого нам потребуется немного изменить его следующим образом:
Скрипт мы поправили, теперь давайте немного под шаманим шаблон, заменим содержимое C# кубика следующим содержанием:
А мы все ближе! К чему? ....
Что теперь мы получаем? а мы получаем JSON в котором описан наш клиент, ну вы в данном случае. Это отлично! Но мы сразу позаботимся о том что, возможна ситуация когда клиента нет в списке клиентов. И если мы не смогли найти по хешу клиента тогда шаблон получит вот такой JSON:
Давайте его обработаем, и для этого изменим в C# кубике все строки на код ниже:
Лирическое отступление для тех кто все проделывает шаг за шагом:
Чтобы у вас все заработало вам нужно в шаблоне добавить модуль "Добавить ссылки из GAC", и добавить либу "System.Web.Extensions", я нарисовал путь мышкой на скриншоте:
Я кукарача! )))))))))))))))
Думаем далее! Мы общаемся с нашим "Сервером" лицензирования, нашим "Софтом", но все что мы передаем ему, мы передаем в открытом виде, все параметры можно подделать и сломать нашу систему защиты. Я не буду объяснять как это сделать, я расскажу как от этого защитится.
Короче так, мы нашему серверу, вы заметили, я стал называть скрипт в гугло табличке сервером лицензирования, это не спроста. И так нашему серверу поступают данные: емаил, дата текущая и хеш. Как нам должен ответить сервер чтобы избежать подделки данных? - а все просто: Сервер должен возвращать в ответе хеш доступа и состояние лицензии. Давайте подумаем как....
А давайте, наш сервер будет высчитывать количество секунд, которое осталось по его данным на использование шаблона. Но не просто так, а в виде какого нибудь хеша. И вот тут мы понимаем что гугло скрипты особо та и не умеют рассчитывать стойки МД5. Но это поправимо. Добавьте код приведенный ниже в наш гугло скрипт.
Этот код я сдернул в сети, с какого-то сайта очень древней наружности, и разбирать его мы с вами не будем, скажу одно он позволяет получить хешь от обекта, что нас устаревает на 100500%!
Ну так что на счет расчетов? Давайте думать: мы знаем текущее время у клиента, так как передаем его в запросе, мы знаем время когда кончится лицензия у клиента, это хранится в таблице. Ну так давайте получим разницу этих дат в секундах, и от полученного возьмем хеш. Для этого исправим код гугл скрипта на следующий:
И внесем исправления в код кубика C# всамом шаблоне:
Вот ребятки такая штука получилась. Шаблон и текст гугло скрипта приложу.
Интро:
Весь код, который тут представлен, написан на C# за исключением скриптов гугл ). Тем кто не разбирается в Шарпе, рекомендую уделить время по изучать его, ну или использовать готовое решение в своих целях. Я сам так часто поступаю .
Интро2:
Сидел писал статью и на Складчике пришло уведомление, что появился новый ответ в отслеживаемой теме, как оказалось апнули довольно старую тему по защите шаблонов от уважаемого @Moadip, оценив его идею и свои наработки пришел к выводу, что скорее всего он меня натолкнул на этот краеугольный камень ))). Отмечу что наши идеи схожи, но реализации разные.
Стартуем:
Итак, с чего начнем - для тех кто не знает, шаблоны можно зашифровать и установить в них права стандартным модулем zennoposter "Шифрование"
Казалось бы этого достаточно, но не тут то было )) многие, кто оказывает услуги по разработке шаблонов, сталкивались с нерадивыми заказчиками, которые получали решение, а оплачивать отказывались; пару топиков тут уже проскакивали с гневом шаблонописцев. Что делать? Можно воспользоваться личным кабинетом, разделом боты и не заморачиваться для тех кто не в курсе смотреть сюда https://userarea.zennolab.com/lk/login.aspx
- Ну вот теперь та проблема решена же!
Да, можно и так защитить свой труд, но ведь все мы ушлые ребятки и не хотим морозить 10-20-100 баксов на счету в ЛК ЗенноЛаба (@nuaru ни чего личного . Я просто хочу рассказать, что делаю сам и ни в коей мере не призываю отказаться от выписки шаблонов через ЛК! )
А мы с вами тем временем пойдем по другому пути. Итак, давайте создадим пустой проект и накидаем в него пару кубиков , ну 3 если быть точным.
Думаю тут нет вопросов ни у кого...
Идем далее, давайте подумаем как бы нам защищаться, та?
Самый очевидный путь собрать какие то данные из окружения зенки и/или ПК и что-то с ними сделать.
На ум приходит сразу то, что зенка привязана к e-mail, который не меняется. Давайте его и будем использовать.
А как нам его получить? Да очень просто:
Код:
return Microsoft.Win32.Registry.CurrentUser.OpenSubKey("SOFTWARE\\ZennoLab").GetValue("login").ToString();
Думаем дальше:
Хочу, чтобы я мог ограничивать работу шаблона в каком то периоде: часы, дни, годы. Ну и отлично Значит, нам нужно сохранять дату каким-то образом.
О! Забыли подумать над тем, что на каждом компе время может отличаться(разные часовые пояса), ну для этого у наст есть стандартизация времени по-Гринвичу и, чтобы получить текущую дату по Гринвичу, нужно выполнить такой код:
Код:
return DateTime.UtcNow.ToString("MM/dd/yyyy HH:mm");
Отличненько, что далее?
Теперь нам нужно каким-то образом где-то проверить, а может шаблон работать или нет. Другими словами, нам нужно где-то что-то посмотреть и узнать, что шаблон может запускаться.
Ну, так давайте уже знакомиться с сервисом google script app!
Сперва создадим пустую гугл табличку и посмотрим на вкладку инструменты:
Конечно же тыкайте на "Редактор скриптов", я думал вы уже тыкнули . Главное потом нажмите сюда
У вас, скорее всего, там будет пусто, а у меня уже есть пару боевых скриптов.
Полагаю, что вы же ткнули "Создание проекта" и увидели вот такую картинку:
стираем там все, что написано и пишем код:
Java:
function doPost() {
}
function doGet() {
}
Что дальше? А давайте исправим doGet так, чтобы он нам возвращал те данные, которые мы ему передали. Исправьте скрипт следующим образом:
Java:
function doPost(e) {
}
function doGet(e) {
var s = e.parameter.mail + " " + e.parameter.date;
//строчка ниже просто возвращает то, что пришло гет запросом
return ContentService.createTextOutput(s).setMimeType(ContentService.MimeType.TEXT);
}
Как вы видите из кода, функция doGet принимает один объект - e, который содержит в себе все параметры, переданные запросом в УРЛ. В нашем случае использовано 2 параметра mail и date.
Ну вот, пришла пора выставить скрипт наружу. Для этого сделаем следующее:
Нажмем на кнопку.
Теперь выполним следующие действия:
Версия: новый
Как запускать: От моего имени
Кто имеет доступ: Все, включая анонимных
И, нажимаем "Развернуть", после чего гугл попросит нас подтвердить разрешение на внесение изменений, мы, конечно же, соглашаемся! А может и не попросит У меня перестал просить, наверное от того, что я все скрипты храню в одной таблице.
Копируем урл скрипта. Он появится в отдельном окошке, но если вы забыли его скопировать, то нажмите "Публикация" - "Развернуть как веб приложение" и вверху увидите заветный УРЛ скрипта.
ВАЖНО! Если вы внесли какие-то изменения в скрипт, то вам нужно провести процедуру публикации и указать версию "НОВЫЙ".
Для тех, кто любит читать по Англицки, кидаю фулдок по веб АПП https://developers.google.com/apps-script/guides/web
Урл скопировали, давайте вернемся к шаблону.
В кубик C# добавим такой код, запустим его на выполнение и посмотрим, что получили:
C#:
//Где опубликован скрипт
string licUrl = "https://script.google.com/ ТУТ ДОЛЖЕН БЫТЬ УРЛ ВАШЕГО СКРИПТА";
//Параметры полученые шаблоном
string mail = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("SOFTWARE\\ZennoLab").GetValue("login").ToString();
string date = DateTime.UtcNow.ToString("MM/dd/yyyy HH:mm");
//Форматируем параметры
string parameter = string.Format("?mail={0}&date={1}", mail, date);
//отправляем запрос
string response = ZennoPoster.HttpGet(licUrl + parameter, "", "UTF-8", InterfacesLibrary.Enums.Http.ResponceType.BodyOnly);
return response;
Отлично! Двигаемся далее.
Действиями выше, мы связали зенку с GAS. Теперь, давайте думать, что у нас будет в бэкэнде - содержание гугл таблички.
Очевидно, что в табличке мы должны хранить электронный адрес клиента, дату, до которой он может пользоваться шаблоном, а так же название шаблона. Вот такую табличку давайте и сделаем.
Как вы видите на скрине, я добавил еще одно поле - "HASH". А зачем спросите вы? Так будет проще искать нужную строчку в таблице. Т.е. вместо того, чтобы делать два запроса к таблице (Сначала найдем все строки по полю Client, а потом из этих строк будем искать TemplateName), мы будем искать по одному полю под названием "HASH", а значение этого поля будет рассчитано таким образом:
C#:
return Convert.ToString(mail + project.Name).GetMD5Hash();
ОК! Теперь давайте научим наш гугло скрипт искать данные в таблице, а для этого нам потребуется немного изменить его следующим образом:
Java:
function doGet(e) {
var h = e.parameter.HASH; // возмем хешь из параметров
var client = getClientPermit(h); // найдем клиента
return ContentService.createTextOutput(JSON.stringify(client)).setMimeType(ContentService.MimeType.TEXT);//ответим шаблону
}
//Получим разрешение
function getClientPermit(h){
//вот прям ща создадим объект в который сложим результат поиска пользователя
var Clients = getClientsObject(getTebleRows().getDataRange().getValues()); //Прочитаем все таблицу
return searchClientFromClientsHASH(h, Clients); //вернем объект
}
//Эта функция создает удобный для нас массив объектов содержащий строки таблички
function getClientsObject(range) {
var rowObjects = [];
for (var i = 1; i < range.length; i++) {
var row = {Client: range[i][0], ExpiredDate: range[i][1], TemplateName: range[i][2], HASH:range[i][3]};
rowObjects.push(row);
}
return rowObjects;
}
//Эта функция ищет нам данные о клиенте по хешу
function searchClientFromClientsHASH(hash, Clients){
for (var i = 0; i < Clients.length; i++) {
if (Clients[i].HASH == hash)
return Clients[i];
}
return {error: 'Клиент не найден!', code: 0};
}
function getTebleRows(){
// Откроем таблицу по ИД
var tid = 'вставьте свой'; // это ид таблицы, он берется из урл самой таблицы
var sheet = SpreadsheetApp.openById(tid).getSheetByName('Clients');
return sheet;
}
C#:
//Где опубликован скрипт, я думаю понятно что нужно вставить урл вашего скрипта
string licUrl = "https://script.google.com/a/zhag/ваш ид скрипта/exec";
//Параметры полученые шаблоном
string mail = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("SOFTWARE\\ZennoLab").GetValue("login").ToString();
string date = DateTime.UtcNow.ToString("MM/dd/yyyy HH:mm");
//Форматируем параметры
string parameter = string.Format("?mail={0}&date={1}&HASH={3}", mail, date, Convert.ToString(mail + project.Path));
//отправляем запрос
string response = ZennoPoster.HttpGet(licUrl + parameter, "", "UTF-8", InterfacesLibrary.Enums.Http.ResponceType.BodyOnly);
return response;
А мы все ближе! К чему? ....
Что теперь мы получаем? а мы получаем JSON в котором описан наш клиент, ну вы в данном случае. Это отлично! Но мы сразу позаботимся о том что, возможна ситуация когда клиента нет в списке клиентов. И если мы не смогли найти по хешу клиента тогда шаблон получит вот такой JSON:
Код:
{"error":"Клиент не найден!","code":0}
C#:
JavaScriptSerializer ser = new JavaScriptSerializer();
//Где опубликован скрипт
string licUrl = "https://script.google.com/a/z";
//Параметры полученые шаблоном
string mail = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("SOFTWARE\\ZennoLab").GetValue("login").ToString();
string date = DateTime.UtcNow.ToString("MM/dd/yyyy HH:mm");
//Форматируем параметры
string parameter = string.Format("?mail={0}&date={1}&HASH={3}", mail, date, Convert.ToString(mail + project.Path));
//отправляем запрос
string response = ZennoPoster.HttpGet(licUrl + parameter, "", "UTF-8", InterfacesLibrary.Enums.Http.ResponceType.BodyOnly);
//Сделаем словарь из ответа нашего гугл скрипта
Dictionary<string, dynamic> d = ser.Deserialize<Dictionary<string, dynamic>>(response);
//проверем чтобы мы нашли клиента 100%
if(d.ContainsKey("error")){//Если не нашли клиента
ZennoPoster.StopTask(Guid.Parse(project.TaskId)); // остановим выполнение шаблона
throw new Exception(d["error"] + " Oбратитесь в телеграм к разработчику @zhagru");
}
return response;
Лирическое отступление для тех кто все проделывает шаг за шагом:
Чтобы у вас все заработало вам нужно в шаблоне добавить модуль "Добавить ссылки из GAC", и добавить либу "System.Web.Extensions", я нарисовал путь мышкой на скриншоте:
Я кукарача! )))))))))))))))
Думаем далее! Мы общаемся с нашим "Сервером" лицензирования, нашим "Софтом", но все что мы передаем ему, мы передаем в открытом виде, все параметры можно подделать и сломать нашу систему защиты. Я не буду объяснять как это сделать, я расскажу как от этого защитится.
Короче так, мы нашему серверу, вы заметили, я стал называть скрипт в гугло табличке сервером лицензирования, это не спроста. И так нашему серверу поступают данные: емаил, дата текущая и хеш. Как нам должен ответить сервер чтобы избежать подделки данных? - а все просто: Сервер должен возвращать в ответе хеш доступа и состояние лицензии. Давайте подумаем как....
А давайте, наш сервер будет высчитывать количество секунд, которое осталось по его данным на использование шаблона. Но не просто так, а в виде какого нибудь хеша. И вот тут мы понимаем что гугло скрипты особо та и не умеют рассчитывать стойки МД5. Но это поправимо. Добавьте код приведенный ниже в наш гугло скрипт.
Java:
String.prototype.MD5 = function(charset, toByte) {
charset = charset || Utilities.Charset.UTF_8;
var digest = Utilities.computeDigest(Utilities.DigestAlgorithm.MD5, this, charset);
if(toByte) return digest;
var __ = '';
for (i = 0; i < digest.length; i++) {
var byte = digest[i];
if (byte < 0) byte += 256;
var bStr = byte.toString(16);
if (bStr.length == 1) bStr = '0' + bStr;
__ += bStr;
}
return __;
}
Этот код я сдернул в сети, с какого-то сайта очень древней наружности, и разбирать его мы с вами не будем, скажу одно он позволяет получить хешь от обекта, что нас устаревает на 100500%!
Ну так что на счет расчетов? Давайте думать: мы знаем текущее время у клиента, так как передаем его в запросе, мы знаем время когда кончится лицензия у клиента, это хранится в таблице. Ну так давайте получим разницу этих дат в секундах, и от полученного возьмем хеш. Для этого исправим код гугл скрипта на следующий:
Java:
function doGet(e) {
var salt = "сольМоя"; //это дополнителная строка которую добовляем при получении хеша, чтоб его ни кто не мог расчитать без нас
var h = e.parameter.HASH; // возмем хешь из параметров
var client = getClientPermit(h); // найдем клиента
var sicret = salt.MD5() + getSecondsWork(client.ExpiredDate, e.parameter.date).toString().MD5();// составим сикретные данные
client.s = sicret; // добавим хеш к ответу сервера
return ContentService.createTextOutput(JSON.stringify(client)).setMimeType(ContentService.MimeType.TEXT);//ответим шаблону
}
//Получим разрешение
function getClientPermit(h){
//вот прям ща создадим объект в который сложим результат поиска пользователя
var Clients = getClientsObject(getTebleRows().getDataRange().getValues()); //Прочитаем все таблицу
return searchClientFromClientsHASH(h, Clients); //вернем объект
}
//Эта функция создает удобный для нас массив объектов содержащий строки таблички
function getClientsObject(range) {
var rowObjects = [];
for (var i = 1; i < range.length; i++) {
var row = {Client: range[i][0], ExpiredDate: range[i][1], TemplateName: range[i][2], HASH:range[i][3]};
rowObjects.push(row);
}
return rowObjects;
}
//Эта функция ищет нам данные о клиенте по хешу
function searchClientFromClientsHASH(hash, Clients){
for (var i = 0; i < Clients.length; i++) {
if (Clients[i].HASH == hash)
return Clients[i];
}
return {error: 'Клиент не найден!', code: 0};
}
function getTebleRows(){
// Откроем таблицу по ИД
var tid = 'вставьСвойИдТаблици'; // это ид таблицы, он берется из урл самой таблицы
var sheet = SpreadsheetApp.openById(tid).getSheetByName('Clients');
return sheet;
}
//Расчитаем сколько секунд осталось по лицензии
function getSecondsWork(startDate, endDate){//, endDate){
// startDate - это дата которую мы получили от клиента
// endDate - эту дату мы берем из таблицы
return (startDate - new Date(Date.parse(endDate)))/1000;
}
String.prototype.MD5 = function(charset, toByte) {
charset = charset || Utilities.Charset.UTF_8;
var digest = Utilities.computeDigest(Utilities.DigestAlgorithm.MD5, this, charset);
if(toByte) return digest;
var __ = '';
for (i = 0; i < digest.length; i++) {
var byte = digest[i];
if (byte < 0) byte += 256;
var bStr = byte.toString(16);
if (bStr.length == 1) bStr = '0' + bStr;
__ += bStr;
}
return __;
}
И внесем исправления в код кубика C# всамом шаблоне:
C#:
JavaScriptSerializer ser = new JavaScriptSerializer();
//Где опубликован скрипт
string licUrl = "вставьСвойУрлСкрипта";
//Параметры полученые шаблоном
string mail = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("SOFTWARE\\ZennoLab").GetValue("login").ToString();
string date = DateTime.UtcNow.ToString("s")+"Z";
//Форматируем параметры
string parameter = string.Format("?mail={0}&date={1}&HASH={2}", mail, date, Convert.ToString(mail + project.Name).GetMD5Hash());
//отправляем запрос
string response = ZennoPoster.HttpGet(licUrl + parameter, "", "UTF-8", InterfacesLibrary.Enums.Http.ResponceType.BodyOnly);
project.SendInfoToLog(response);
//Сделаем словарь из ответа нашего гугл скрипта
Dictionary<string, dynamic> d = ser.Deserialize<Dictionary<string, dynamic>>(response);
//проверем чтобы мы нашли клиента 100%
if(d.ContainsKey("error")){//Если не нашли клиента
ZennoPoster.StopTask(Guid.Parse(project.TaskId)); // остановим выполнение шаблона
throw new Exception(d["error"] + " Oбратитесь в телеграм к разработчику @zhagru");
}
//расчитываем количество секунд оставшихся до конца лицензии
TimeSpan t = DateTime.Parse(d["ExpiredDate"]) - DateTime.Parse(date);
int i = (int)t.TotalMilliseconds/1000; // проверим что еще есть время для работы, если тут получим отрицательное число, то лицензия кончилась
//проверяем можно работать или нет
if(i<0) throw new Exception(d["ExpiredDate"] + " закончилась лицензия");
string salt = "сольМоя"; // это секретное слово которое должно совпадать с секретным словом в гугл скрипте
project.SendInfoToLog(Convert.ToString(salt + i.ToString()).GetMD5Hash());
if(d["s"] == salt.GetMD5Hash() + i.ToString().GetMD5Hash()){//сверим хеши
return "";
}
else
throw new Exception(d["ExpiredDate"] + " закончилась лицензия");
Вот ребятки такая штука получилась. Шаблон и текст гугло скрипта приложу.
- Тема статьи
- Другое
- Номер конкурса статей
- Восьмой конкурс статей
Вложения
-
22,6 КБ Просмотры: 477
Для запуска проектов требуется программа ZennoPoster или ZennoDroid.
Это основное приложение, предназначенное для выполнения автоматизированных шаблонов действий (ботов).
Подробнее...
Для того чтобы запустить шаблон, откройте нужную программу. Нажмите кнопку «Добавить», и выберите файл проекта, который хотите запустить.
Подробнее о том, где и как выполняется проект.
Последнее редактирование: