Русский
Русский
English
Статистика
Реклама

Api вконтакте

В VK добавили Callback кнопки для ботов

25.07.2020 16:11:23 | Автор: admin

Использовать callback.


Доброго времени суток, уважаемые жителя Хабра)
Мой первый пост. Будет кратко, емко и надеюсь актуально.


9го июля ВК выкатил callback кнопки для чат-ботов. Телеграм напрягся сделал это в 199... давно. Самая популярная библиотека для разработки чат-ботов под ВК на Python vk_api (от разработчика python273). Ввиду того, что свежие правки в нее вносятся медленно, я взял на себя смелось сделать форк, дополнить его и описать небольшой пример использования.


Что сделано относительно исходной v11.80?


  1. Обновлены ограничения по клавиатуре (в соответствии с изменениями в API):


    • не более 5 кнопок в строке (было 4);
    • не более 10 и 6 строк для стандартного и inline представления соответственно (было 10 и там, и там);
    • Default кнопка переименована в Secondary.

  2. Добавлены callback-кнопки:


    • новый тип события "message_event" (клик по кнопке);
    • новый метод "создать callback кнопку";
    • добавлен example (анимация работы и код будут приведены ниже).


Виды callback кнопок


У сallback кнопок 3 встроенных действия по клику (+ редактирование сообщения):


  1. show_snackbar показать всплывающее сообщение (исчезает через 10 сек);
  2. open_link открыть URL ссылку;
  3. open_app открыть ВК приложение;
  4. можно настроить редактирование текущего сообщения, дабы по клику можно было изменять клавиатуру + текст в текущем сообщении.

Как установить модифицированную библиотеку?


pip install git+https://github.com/chebotarevmichael/vk_api

Код примера по частям


Импорты. Думаю, с ними все понятно.


from vk_api import VkApifrom vk_api.utils import get_random_idfrom vk_api.bot_longpoll import VkBotLongPoll, VkBotEventTypefrom vk_api.keyboard import VkKeyboard, VkKeyboardColorimport json

Настройка и запуск бота. Указываем идентификатор и longpoll-токен группы.
Для использования кнопки "открыть ВК приложение" указываем идентификатор приложения и его владельца.


# ОбщиеGROUP_ID = '100...500'GROUP_TOKEN = 'df2148cc7c664...токен_группы....df2148cc7c6642242531fad399'API_VERSION = '5.120'# для callback-кнопки "открыть приложение"APP_ID = 100500         # id IFrame приложенияOWNER_ID = 123456      # id владельца приложения# виды callback-кнопокCALLBACK_TYPES = ('show_snackbar', 'open_link', 'open_app')# Запускаем ботvk_session = VkApi(token=GROUP_TOKEN, api_version=API_VERSION)vk = vk_session.get_api()longpoll = VkBotLongPoll(vk_session, group_id=GROUP_ID)

Создаем два меню.
В первом меню все 4 упомянутых выше действия кнопок.
Во втором только кнопка "назад", возвращающая предыдущее меню.


.


# Настройки для обоих клавиатурsettings = dict(one_time=False, inline=True)# 1. Клавиатура с 3 кнопками: "показать всплывающее сообщение", "открыть URL" и изменить меню (свой собственный тип)keyboard_1 = VkKeyboard(**settings)# pop-up кнопкаkeyboard_1.add_callback_button(label='Покажи pop-up сообщение', color=VkKeyboardColor.SECONDARY, payload={"type": "show_snackbar", "text": "Это исчезающее сообщение"})keyboard_1.add_line()# кнопка с URLkeyboard_1.add_callback_button(label='Откртыть Url', color=VkKeyboardColor.POSITIVE, payload={"type": "open_link", "link": "https://vk.com/dev/bots_docs_5"})keyboard_1.add_line()# кнопка по открытию ВК-приложенияkeyboard_1.add_callback_button(label='Открыть приложение', color=VkKeyboardColor.NEGATIVE, payload={"type": "open_app", "app_id": APP_ID, "owner_id": OWNER_ID, "hash": "anything_data_100500"})keyboard_1.add_line()# кнопка переключения на 2ое менюkeyboard_1.add_callback_button(label='Добавить красного ', color=VkKeyboardColor.PRIMARY, payload={"type": "my_own_100500_type_edit"})# 2. Клавиатура с одной красной callback-кнопкой. Нажатие изменяет меню на предыдущее.keyboard_2 = VkKeyboard(**settings)# кнопка переключения назад, на 1ое меню.keyboard_2.add_callback_button('Назад', color=VkKeyboardColor.NEGATIVE, payload={"type": "my_own_100500_type_edit"})

Запускаем long poll.


Запускаем действо. Если пользователь присылает текстовое сообщение выдаем первое меню. Если это событие "клик по callback кнопке" выполняем определенное действие (одно из 3+1 действий, упомянутых выше).


f_toggle: bool = Falsefor event in longpoll.listen():    # отправляем меню 1го вида на любое текстовое сообщение от пользователя    if event.type == VkBotEventType.MESSAGE_NEW:        if event.obj.message['text'] != '':            if event.from_user:                # Если клиент пользователя не поддерживает callback-кнопки,                # нажатие на них будет отправлять текстовые                # сообщения. Т.е. они будут работать как обычные inline кнопки.                if 'callback' not in event.obj.client_info['button_actions']:                    print(f'Клиент {event.obj.message["from_id"]} не поддерж. callback')                vk.messages.send(                        user_id=event.obj.message['from_id'],                        random_id=get_random_id(),                        peer_id=event.obj.message['from_id'],                        keyboard=keyboard_1.get_keyboard(),                        message=event.obj.message['text'])    # обрабатываем клики по callback кнопкам    elif event.type == VkBotEventType.MESSAGE_EVENT:        # если это одно из 3х встроенных действий:        if event.object.payload.get('type') in CALLBACK_TYPES:            # отправляем серверу указания как какую из кнопок обработать. Это заложено в             # payload каждой callback-кнопки при ее создании.            # Но можно сделать иначе: в payload положить свои собственные            # идентификаторы кнопок, а здесь по ним определить            # какой запрос надо послать. Реализован первый вариант.            r = vk.messages.sendMessageEventAnswer(                      event_id=event.object.event_id,                      user_id=event.object.user_id,                      peer_id=event.object.peer_id,                                                                         event_data=json.dumps(event.object.payload))        # если это наша "кастомная" (т.е. без встроенного действия) кнопка, то мы можем        # выполнить edit сообщения и изменить его меню. Но при желании мы могли бы        # на этот клик открыть ссылку/приложение или показать pop-up. (см.анимацию ниже)        elif event.object.payload.get('type') == 'my_own_100500_type_edit':            last_id = vk.messages.edit(                      peer_id=event.obj.peer_id,                      message='ola',                      conversation_message_id=event.obj.conversation_message_id,                      keyboard=(keyboard_1 if f_toggle else keyboard_2).get_keyboard())            f_toggle = not f_toggleif __name__ == '__main__':    print()

Как выглядит процесс


Использовать callback.


Заключение


Тот факт, что callback-кнопки наконец-то появились в ВК радует. И пусть пока они работают только под мобильными приложениями, а в браузере не поддерживают. Пусть в браузере inline-кнопки все еще не выравнивается по ширине. Все же их наличие хоть в каком-то виде искренне радует меня, как разработчика коммерческого телеграмм-бота.


Теперь появилась возможность реализовать ВК-интерфейс для своего телеграм-бота, где в разы больше жителей РФ, т.е целевой аудитории. Этот факт заставляет мириться со всеми перечисленными неудобствами и минусами, и идти к горе, раз она не хочет идти к Магомеду. На скриншоте ниже реализация одного и того же интерфейса через callback-кнопки: справа в Телеграм, и слева ВКонтакте.


.


Надеюсь, кому-то этот краткий обзор поможет начать использовать callback кнопки в своих ботах. Pull-request автору библиотеки отправлен.

Подробнее..

Дешифровка текста методом частотного анализа

05.08.2020 14:08:45 | Автор: admin

Привет, Хабр! В этой статье я покажу как сделать частотный анализ современного русского интернет-языка и воспользуюсь им для расшифровки текста. Кому интересно, добро пожаловать под кат!


s1200


Частотный анализ русского интернет-языка


В качестве источника, откуда можно взять много текста с современным интернет-языком, была взята социальная сеть Вконтакте, а если быть точнее, то это комментарии к публикациям в различных сообществах данной сети. В качестве сообщества я выбрал реальный футбол. Для парсинга комментариев я воспользовался API Вконтакте:


def get_all_post_id():    sleep(1)    offset = 0    arr_posts_id = []    while True:        sleep(1)        r = requests.get('https://api.vk.com/method/wall.get',                         params={'owner_id': group_id, 'count': 100,                                  'offset': offset, 'access_token': token,                                   'v': version})        for i in range(100):            post_id = r.json()['response']['items'][i]['id']            arr_posts_id.append(post_id)        if offset > 20000:            break        offset += 100    return arr_posts_iddef get_all_comments(arr_posts_id):    offset = 0    for post_id in arr_posts_id:        r = requests.get('https://api.vk.com/method/wall.getComments',                         params={'owner_id': group_id, 'post_id': post_id,                                  'count': 100, 'offset': offset,                                  'access_token': token, 'v': version})        for i in range(100):            try:                write_txt('comments.txt', r.json()                ['response']['items'][i]['text'])            except IndexError:                pass

В результате было получено около 200MB текста. Теперь считаем, какой символ сколько раз встречается:


f = open('comments.txt')counter = Counter(f.read().lower())def count_letters():    count = 0    for i in range(len(arr_letters)):        count += counter[arr_letters[i]]    return countdef frequency(count):    arr_my_frequency = []    for i in range(len(arr_letters)):        frequency = counter[arr_letters[i]] / count * 100        arr_my_frequency.append(frequency)    return arr_my_frequency

Полученные результаты можно сравнить с результатами из Википедии и отобразить в виде:


1) сравнительной диаграммы


frequency_0


2) таблицы(слева данные википедии, справа мои данные)


frequency_1


Проанализировав данные, можно сделать вывод, что частота встречаемости символов в процентном соотношении в двух источниках практически одинакова, за исключением таких букв как а и о.


Шифрование и дешифрование текста


Далее я выбрал из того же сообщества более развёрнутый комментарий, который найти было не так уж и легко, так как в основном комментарии состоят из 2-4 слов:


Снимок экрана от 2020-07-27 20-07-06


дружа слово почти не считается, вар извинилась за неправильное решение, и этого достаточно чтобы сделать вывод и усомниться во многих их решениях, вар вместо того чтобы исключать ошибки делает их, это абсолютно не нормально, народ не такой уже и тупой, не по радио же слушаем транслы а в живую смотрим, по этому я больше чем уверен если бы не было столько пенок для мю они бы подавно в топ не попали, аналогично касается ман с, хотя играют местами захватывающе и красиво


После этого необходимо зашифровать полученный текст с помощью какого-нибудь симметричного алгоритма шифрования. Первое, что приходит на ум это шифр цезаря, сущность которого заключается в том, чтобы изменить символ на другой с определенным шагом:


def caesar_cipher():    file = open("text.txt")    text_for_encrypt = file.read().lower().replace(',', '')    letters = 'абвгдеёжзийклмнопрстуфхцчшщъыьэюя'    arr = []    step = 3    for i in text_for_encrypt:        if i == ' ':            arr.append(' ')        else:            arr.append(letters[(letters.find(i) + step) % 33])    text_for_decrypt = ''.join(arr)    return text_for_decrypt

жуцйг фосес тсъхл рз фълхгзхфв егу лкелрлогфя кг рзтугелоярсз узызрлз л ахсёс жсфхгхсърс ъхсдю фжзогхя еюесж л цфспрлхяфв ес прсёлш лш узызрлвш егу епзфхс хсёс ъхсдю лфнобъгхя сылднл жзогзх лш ахс гдфсобхрс рз рсупгоярс ргусж рз хгнсм цйз л хцтсм рз тс угжлс йз фоцыгзп хугрфою г е йлецб фпсхулп тс ахспц в дсояыз ъзп цезузр зфол дю рз дюос фхсоянс тзрсн жов пб срл дю тсжгерс е хст рз тстгол гргосёлърс нгфгзхфв пгр ф шсхв лёугбх пзфхгпл кгшегхюегбьз л нугфлес


Затем осталось расшифровать текст с помощью частотного анализа:


def decrypt_text(text_for_decrypt, arr_decrypt_letters):    arr_encrypt_text = []    arr_encrypt_letters = [' ', 'о', 'а', 'е', 'и', 'т', 'н', 'л',                           'р', 'с', 'в', 'к', 'м', 'д', 'у', 'п',                           'б', 'г', 'ы', 'ч', 'ь', 'з', 'я', 'й',                           'х', 'ж', 'ш', 'ю', 'ф', 'э', 'щ',                           'ё', 'ц', 'ъ']    dictionary = dict(zip(arr_decrypt_letters, arr_encrypt_letters))    for i in text_for_decrypt:        arr_encrypt_text.append(dictionary.get(i))    text_for_decrypt = ''.join(arr_encrypt_text)    print(text_for_decrypt)

двужа лросо мопти не лпитаетлб сав ишсиниралг ша немвасиргное вейение и ютохо долтатопно птоыч лдератг счсод и улокнитглб со кнохиз из вейенибз сав скелто тохо птоыч ильряпатг ойиыьи дерает из юто аылорятно не новкаргно навод не таьоф уже и тумоф не мо вадио же лруйаек тванлрч а с жисуя лкотвик мо ютоку б ыоргйе пек усевен елри ыч не ычро лторгьо меноь дрб кя они ыч модасно с том не момари анарохипно ьалаетлб кан л зотб ихваят келтаки шазсатчсаяэе и ьвалисо


Заключение


Если посмотреть на расшифрованный текст, то можно догадаться, где наш алгоритм ошибся: дерает делает, вадио радио, тохо того, навод народ. Таким образом, можно расшифровать весь текст, по крайне мере, уловить смысл текста. Также хочу отметить, что данный метод будет эффективный в расшифровке только длинных текстов, которые были зашифрованы симметричными методами шифрования. Полный код доступен на Github .

Подробнее..

Бот для автопостинга VK

27.09.2020 20:23:04 | Автор: admin
ВНИМАНИЕ: статья создана только в обучающих целях, я не призываю Вас использовать продукт полученный в конце урока для принесения неудобств или собственной выгоды


Что будем делать


Бота для автопостинга записей на стене сообщества или страницы Vk

Зачем


Для ознакомительных целей

Что нам понадобится




Начнем


Для работы нам понадобится токен с разрешениями wall и offline. Для получения токена создайте свое Standalone-приложение Vk. И сохраните его ID.

Далее перейдите по ссылке:
oauth.vk.com/authorize?client_id=IDAPP&scope=wall,offline&redirect_uri=http://api.vk.com/blank.html&response_type=token
И вместо IDAPP подставьте ID своего приложения. Или воспользуйтесь ссылкой, которую я подготовил специально для Вас.

Если все сделано правильно Вас перекинет на другой сайт, а в URL странице в GET параметре access_token будет токен, который нам и нужен, сохраняем его.

Работа XML


Для хранения настроек созданим файл формата .xml со следующем контентом:
<settings>  <token>token</token>  <textPost>Text post</textPost>  <interval>120</interval>    <post>    <attachments>      <attachment>attachment</attachment>    </attachments>    <copyright>copyright</copyright>    <v>5.122</v>  </post>    <groups>    <group>short name group</group>  </groups></settings>


Замените:
  • token на токен, который мы получили выше
  • Text post на сообщение, которое должно быть в записи
  • attachment на объект, который будет прикреплен к записи
  • copyright на ссылку источника
  • short name group на короткое имя(без vk.com) страницу сообщества/ пользователя, где будет проходить публикация(стена должна быть открытой для публикации)


Начнем писать код


Импортируем все нужные библиотеки, создадим экземпляр нашего модуля и авторизуемся во вконтакте от лица пользователя через токен.
import vk_apiimport timefrom modules import XML as moduleXmlXML = moduleXml.XML("settings")VK = vk_api.VkApi(token=XML.parsingFile("token"))


Далее получим все короткие адреса, где будут публиковаться записи.
import vk_apiimport timefrom modules import XML as moduleXmlXML = moduleXml.XML("settings")VK = vk_api.VkApi(token=XML.parsingFile("token"))groupsId = []groupsShortName = ""for child in XML.parsingFile("groups", False):    groupsShortName += child.text + ","for group in VK.method("groups.getById", {"group_ids": groupsShortName}):    groupsId.append(group["id"] * -1)del groupsShortName


Теперь получим сообщение, которое будет в записи, интервал, с которым будут публиковаться записи и источник записи.
import vk_apiimport timefrom modules import XML as moduleXmlXML = moduleXml.XML("settings")VK = vk_api.VkApi(token=XML.parsingFile("token"))groupsId = []groupsShortName = ""for child in XML.parsingFile("groups", False):    groupsShortName += child.text + ","for group in VK.method("groups.getById", {"group_ids": groupsShortName}):    groupsId.append(group["id"] * -1)del groupsShortNametextPost = XML.parsingFile("textPost")intervalPost = int(XML.parsingFile("interval"))


Теперь получим все объекты, которые будут прикреплены к записи.
import vk_apiimport timefrom modules import XML as moduleXmlXML = moduleXml.XML("settings")VK = vk_api.VkApi(token=XML.parsingFile("token"))groupsId = []groupsShortName = ""for child in XML.parsingFile("groups", False):    groupsShortName += child.text + ","for group in VK.method("groups.getById", {"group_ids": groupsShortName}):    groupsId.append(group["id"] * -1)del groupsShortNametextPost = XML.parsingFile("textPost")intervalPost = int(XML.parsingFile("interval"))attachments = [attachment.text for attachment in XML.parsingFile("attachments", False)]copyright = XML.parsingFile("copyright")v = XML.parsingFile("v")


У нас уже есть все данные, которые нам понадобятся для публикации. Осталось только сделать функцию для публикации и цикл, который будет вызывать функцию публикации.

Сначала сделаем цикл, а функцию оставим пустой. Так же код будет работать, только если будет запущен из консоли.

import vk_apiimport timefrom modules import XML as moduleXmlXML = moduleXml.XML("settings")VK = vk_api.VkApi(token=XML.parsingFile("token"))groupsId = []groupsShortName = ""for child in XML.parsingFile("groups", False):    groupsShortName += child.text + ","for group in VK.method("groups.getById", {"group_ids": groupsShortName}):    groupsId.append(group["id"] * -1)del groupsShortNametextPost = XML.parsingFile("textPost")intervalPost = int(XML.parsingFile("interval"))attachments = [attachment.text for attachment in XML.parsingFile("attachments", False)]copyright = XML.parsingFile("copyright")v = XML.parsingFile("v")done = Falsedef publicPosts():    passif __name__ == "__main__":    done = Truewhile done:    publicPosts()    time.sleep(intervalPost)


Чтобы публиковать запись будем вызвать метод API wall.post и передавать параметры получение раньше. Если все сработает правильно будет выводится соответствующее сообщение в консоль.

import vk_apiimport timefrom modules import XML as moduleXmlXML = moduleXml.XML("settings")VK = vk_api.VkApi(token=XML.parsingFile("token"))groupsId = []groupsShortName = ""for child in XML.parsingFile("groups", False):    groupsShortName += child.text + ","for group in VK.method("groups.getById", {"group_ids": groupsShortName}):    groupsId.append(group["id"] * -1)del groupsShortNametextPost = XML.parsingFile("textPost")intervalPost = int(XML.parsingFile("interval"))attachments = [attachment.text for attachment in XML.parsingFile("attachments", False)]copyright = XML.parsingFile("copyright")v = XML.parsingFile("v")done = Falsedef publicPosts():    for groupId in groupsId:        for i in range(1, 5):            result = VK.method("wall.post", {                "owner_id": groupId,                "message": textPost,                "attachments": attachments,                "copyright": copyright,                "v": v            })            if result["post_id"]:                print("Good post, id post - " + str(result["post_id"]))            else:                print("Error posting")if __name__ == "__main__":    done = Truewhile done:    publicPosts()    time.sleep(intervalPost)


Заключение


Вот и все, весь код готов. Скажу Вам сразу же мне 13 лет. И я хочу рассказать и поделиться тем, что я умею и считаю интересным для других. Так мою прошлую публикацию прочитали 2к+ человек, а 40 человек сохранили в закладки, хотя там и есть, что доработать. Это меня замотивировала, спасибо Вам большое.

Проект на gitHub.

ВНИМАНИЕ: статья создана только в обучающих целях, я не призываю Вас использовать продукт полученный в конце урока для принесения неудобств или собственной выгоды
Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru