Попытка перевести Object- C в Applescriptobj c для поиска сообщений в Instagram - PullRequest
0 голосов
/ 03 апреля 2020

Итак, у меня есть этот код Objective- C, который делает то, что я пытался обернуть головой с помощью простого Applescript, а также попытался и потерпел неудачу с некоторыми python, которые я попробовал (и потерпел неудачу). Я бы опубликовал приложение, которое я уже пробовал, но оно по сути бесполезно. Поэтому я обращаюсь к гуру AppleScript / ASOBJ C, чтобы помочь с решением. Код предназначен для обратного преобразования идентификатора медиа Instagram в идентификатор записи (поэтому, если у вас есть фотография, которую вы знаете, от IG, вы можете найти идентификатор записи для этой фотографии).

-(NSString *) getInstagramPostId:(NSString *)mediaId {
NSString *postId = @"";
@try {
    NSArray *myArray = [mediaId componentsSeparatedByString:@"_"];
    NSString *longValue = [NSString stringWithFormat:@"%@",myArray[0]];
    long itemId = [longValue longLongValue];
    NSString *alphabet = @"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
    while (itemId > 0) {
        long remainder = (itemId % 64);
        itemId = (itemId - remainder) / 64;
        unsigned char charToUse = [alphabet characterAtIndex:(int)remainder];
        postId = [NSString stringWithFormat:@"%c%@",charToUse , postId];
    }
} @catch(NSException *exception) {
    NSLog(@"%@",exception);
}
return postId;}

Приведенный выше код взят из ответа на другой вопрос SO, который можно найти здесь: Ссылка

Я понимаю, что это, вероятно, много, но я пососать математику, чтобы я действительно не «понял» этот код, поэтому, вероятно, я не могу сам перевести его в какую-то форму Applescript! Надеюсь, я чему-то научусь в этом процессе.

Вот пример идентификатора носителя, который ищет код: 45381714_262040461144618_1442077673155810739_n.jpg А вот идентификатор сообщения, который приведенный выше код должен преобразовать в BqvS62JHYH3

Большая часть исследований, посвященных этим "калькуляторам", содержится в этом посте за 5 лет go. Похоже, что отношение 18 ди git к 10 ди git, которое они указывают в посте, теперь составляет 11 к 19. Я попытался проверить код в XCode, но получил ошибку сборки, когда я попытался запустить его. Учитывая, что я Xcode n00b, это не удивительно.

Спасибо за вашу помощь с этим!

1 Ответ

2 голосов
/ 03 апреля 2020

Вот (почти) дословный перевод вашего Objective- C кода на ASObj C:

use framework "Foundation"
use scripting additions

on InstagramPostIdFromMediaId:mediaId
    local mediaId

    set postId to ""
    set mediaId to my (NSString's stringWithString:mediaId)
    set myArray to mediaId's componentsSeparatedByString:"_"
    set longValue to my NSString's stringWithFormat_("%@", myArray's firstObject())
    set itemId to longValue's longLongValue()
    set alphabet to my (NSString's stringWithString:(("ABCDEFGHIJKLMNOPQRSTUVWXYZ" & ¬
        "abcdefghijklmnopqrstuvwxyz0123456789-_")))

    repeat while (itemId > 0)
        set remainder to itemId mod 64
        set itemId to itemId div 64
        set unichar to (alphabet's characterAtIndex:remainder) as small integer
        set postId to character id unichar & postId
    end repeat

    return postId
end InstagramPostIdFromMediaId:

By "Почти" , Я имею в виду, что каждый метод Objective- C, использованный в исходном скрипте, использовался эквивалентным вызовом того же метода Objective- C через мост ASObj C, с двумя исключениями, Я также сделал тривиальное редактирование математической природы для одной из строк. Таким образом, в общей сложности я произвел три операционных изменений, два из которых являются технически функциональными изменениями, но которые в итоге дают одинаковые результаты:

  1. вместо (itemId - remainder) / 64 с itemId div 64

    • Команда AppleScript div выполняет целочисленное деление , где число, заданное обычным делением, усекается до удалить все после десятичной точки. Это математически идентично тому, что делается, когда remainder вычитается из itemId перед выполнением регулярного деления.
  2. , чтобы избежать случая, когда stringWithFormat: используется для преобразования индекса символов Юникода в строковое представление.

    • NSString объекты хранят строки в виде последовательности кодовых точек UTF-16, а characterAtIndex: будет извлекать конкретный код точка из строки, например, 0x0041, которая относится к символу "A". stringWithFormat: использует спецификатор формата %c для перевода 8-разрядного целого числа без знака (т.е. в диапазоне от 0x0000 до 0x00FF) в его символьное значение. AppleScript мешает этому, хотя я не уверен, как или почему это представляет проблему. Развертывание значения, возвращаемого charactertAtIndex:, дает непрозрачный необработанный объект AppleScript data, который, например, выглядит как «data ushr4100». К счастью, это может быть приведено к типу small integer, возвращающему число 65 в динарах. Поэтому, что бы ни пошло не так, скорее всего, что-то делает stringWithFormat:, поэтому я использовал функцию AppleScript character id ... для выполнения той же операции, что и stringWithFormat:.
  3. myArray[0] был заменен на myArray's firstObject()

    • Оба они используются в Objective- C для извлечения первого элемента в массиве. myArray[0] - это очень знакомый синтаксис C, который можно с радостью использовать в нативном программировании Objective- C, но он недоступен для AppleScript. firstObject - это метод Objective- C, заключающий в себе базовую функцию и делающий ее доступной для использования в любом контексте Objective-C, но, вероятно, также выполняет некоторые дополнительные проверки, чтобы сделать ее подходящей безопасной для использования без особых размышлений. Что касается нас в контексте AppleScript, результат идентичен.

С учетом всего сказанного, mediaId из "45381714_262040461144618_1442077673155810739_n.jpg" наш новый обработчик ASObj C дает такой результат:

"CtHhS"

, а не то, что вы указали в качестве ожидаемого результата, а именно "BqvS62JHYH3". Однако легко понять почему. Оба сценария разбивают mediaId на компоненты («текстовые элементы») при каждом появлении подчеркивания. Затем только первый из них будет использоваться любым сценарием для определения postId. С учетом приведенного выше mediaId первый текстовый элемент - "45381714", что слишком мало для того, чтобы соответствовать нашим потребностям, следовательно, короткая длина ошибочного результата выше. Второй текстовый элемент имеет длину всего 15 цифр (символов), поэтому он также нежизнеспособен. Третий текстовый элемент имеет длину 19 символов, что имеет правильную длину.

Поэтому я заменил firstObject() в сценарии на item 3. Как вы можете догадаться, вместо извлечения первого элемента из массива текстовых элементов (компонентов), хранящихся в myArray, он извлекает третий, а именно "1442077673155810739". Это приводит к следующему результату:

"BQDSgDW-VYA"

Аналогично, но не идентично тому, что вы ожидали.


Пока я оставлю это с вами. На этом этапе я обычно сравнивал бы это с вашими предыдущими попытками, но вы сказали, что они «бесполезны», поэтому я предполагаю, что это, по крайней мере, дает вам кусок переведенного кода, который работает настолько, насколько он выполняет те же операции, что и у его Objective- C. Если вы расскажете нам о характере реальных препятствий, с которыми вы столкнулись, это потенциально позволит мне или кому-то другому помочь в дальнейшем.

Но поскольку я могу с уверенностью сказать, что эти два сценария выполняют одно и то же, то если оригинал производит другой вывод с идентичным вводом, то это говорит нам о том, что данные должны изменяться в какой-то момент во время их обработки. Учитывая, что мы имеем дело с числом порядка 10¹⁹, я думаю, что очень вероятно, что ошибка является результатом точности с плавающей точкой. AppleScript хранит любые целые числа с абсолютным значением вплоть до 536870911 как класс типов integer и все, что превышает его как класс типов real (с плавающей запятой), поэтому будет подвержен ошибкам с плавающей запятой.

...