Пока я разрабатывал и тестировал скрипт для Adrenalin'a на прохождение квестов на ТТ рецепты, я встретил несколько способов, которые и будут описаны ниже. Для удобства я буду рассматривать диалог с Джереми, у которого берутся эти квесты. Для удобного просмотра диалогов в процессе работы можно воспользоваться Script Recorder'ом.

1. Динамически меняющийся bypass. Самый простой случай - сама фраза, которую мы хотим выбрать не меняется, но с каждым новым открытием диалога меняется bypass, который нужно отправить. Обычно данный способ комбинируют с каким-нибудь еще.

<a action="bypass -h  0-739772929">[Доставка ликера (In progress)]</a><br>  // 0-739772929
<a action="bypass -h  01784106480">[Доставка яиц (In progress)]</a><br>   // 01784106480
<a action="bypass -h  0-739859206">[Доставка ликера (In progress)]</a><br>   // 0-739859206
<a action="bypass -h  01784133759">[Доставка яиц (In progress)]</a><br>    // 01784133759

2. Замена одной или нескольких букв в строчке. Длина строки при этом не меняется. Как правило, в исходной строке заменяют пару букв, так что бегло взглянув это можно даже не заметить. Например, вместо "Доставка яиц" будет "Досrавка яиц". Этот способ как раз и используется в дополнение к предыдущему, т.е. при каждом новом открытии диалога меняется и строка ответа и bypass. Данный способ мешает нам искать bypass по заранее известной подстроке:

<a action="bypass -h  01736714927">[Доставка ликdра]</a><br>   // 01736714927
<a action="bypass -h  0-1931249600">[Дeставка яиц]</a><br>   // 0-1931249600
<a action="bypass -h 01736767322">[Доставка лdкера]</a><br>   // 01736767322
<a action="bypass -h 0-1931186782">[Доставка aиц]</a><br>   // 0-1931186782

3. Использование "невидимых" нам спец. символов. Причем как внутри диалога, так и внутри bypass'a . Фактически они присутствуют в диалоге, но при экранировании (т.е. когда нам показывают этот диалог) они не отображаются. Это связано с нестандартными кодировками, кому сильно интересно можете погуглить. По этой же причине я не могу, например, выложить на сайт код этих строк (эти спец символы будут автоматически удалены), поэтому любуемся скриншотами:

В обычном блокноте:

В Sublime Text:

Таким образом, длина искомой подстроки меняется каждый раз, однако последовательность символов в этой подстроке целиком сохранятся.

Возможно есть еще другие виды защит именно на уровне всевозможных модификаций диалогов (вылезающие при открытии диалога каптчи - это отдельный разговор), но мне пока другие не встречались.

Итак, теперь, когда ясна задача, можно думать над тем, как находить заветные bypass's для отправки. Вариантов опять таки несколько, можно решить это, не выходя за рамки функций Pos, Copy, Delete, Trim и тд. Однако проще и красивее будет использовать регулярные выражения (regular expressions). О том, что это и как они составляются можете погуглить. Если кратко, то это поиск по шаблонам, который позволяет нам парсить диалоги в разы проще.

Как пользоваться регулярными выражениями?
Тут все просто, подключаете модуль RegExpr в раздел uses и пользуетесь.

Пример:

uses SysUtils, Classes, RegExpr;  // подключили модуль RegExpr

procedure PrintAllTags();   // распечатать все конструкции с bypass'ами
var RegExp: TRegExpr; 
begin  
  RegExp:= TRegExpr.Create;
  RegExp.Expression:= '(<a *(.+?)</a>)|(<button *(.+?)>)';   
  if RegExp.Exec(Engine.DlgText) then 
    repeat Print(RegExp.Match[0]);
    until (not RegExp.ExecNext);  
  RegExp.Free;
end;

begin
  PrintAllTags();
end.

Этот простой код найдет и распечатает нам все интересующие bypass'ы:

А с помощью этой функции Вы можете выбирать диалоги, обходя 1ый тип защиты:

uses SysUtils, Classes, RegExpr;  // подключили модуль RegExpr

function Bypass(dlg: string): boolean;
var
  RegExp: TRegExpr;
  SL: TStringList;
  i: integer;
  bps: string;
begin
  Result:= true;                                            // задаем результат по умолчанию
  RegExp:= TRegExpr.Create;                                 // инициализируем объекты для дальнейшей работы
  SL:= TStringList.Create;
  
  RegExp.Expression:= '(<a *(.+?)</a>)|(<button *(.+?)>)';  // задаем регэксп на поиск всех возможных bypass'ов 
  if RegExp.Exec(Engine.DlgText) then                       // если нашелся нужный шаблон, то
    repeat SL.Add(RegExp.Match[0]);                         // заполняем наш список такими совпадениями
    until (not RegExp.ExecNext);                            // пока не закончатся шаблоны

  for i:= 0 to SL.Count-1 do begin                          // теперь пробегаемся по нашему списку
    if (Pos(dlg, SL[ i ]) > 0) then begin                   // если в i-ой строке нашелся искомый текст, то
      RegExp.Expression:= '"bypass -h *(.+?)"';             // ищем шаблон текста c bypass'ом
      if RegExp.Exec(SL[ i ]) then                          // и если нашли, то копируем из него интересующий нас кусок
        bps:= TrimLeft(Copy(RegExp.Match[0], 12, Length(RegExp.Match[0])-12));
    end;
  end;
  
  Print(bps);                                               // распечатываем конечный вариант bypass'а
  if (Length(bps) > 0) then Engine.BypassToServer(bps);     // если его длина > 0, то отправляем на сервер
  
  RegExp.Free;                                              // не забываем освобождать память
  SL.Free;
end;

begin
  Bypass('Набор воина');   // непосредственно вызов функции, она найдет соответствующий bypass и отправит его
end.

О правилах составления регулярных выражений полно инфы в инете, например тут

Возможностей много, можете почитать исходники

Надеюсь, что распарсить полученные строчки не составит труда