Всем привет!! Сегодня я хочу показать вам, как легко можно написать первонаха (которого тут продают) на пайтон с помощью vk_api и графического интерфейса tkinter Структура проекта Создаём файл main.py и в этой же директории создаём пустой текстовый файл с названием group.txt У нас должно получиться примерно так Устанавливаем необходимые библиотеки Заходим в терминал PyCharm`a и вводим следующее: pip install vk_api У вас установится библиотека vk_api Импорты Далее в файл main.py прописываем все необходимые импорты import tkinter as tk from vk_api import VkApi import pyperclip import datetime from random import choice import requests import threading import time Python import tkinter as tk from vk_api import VkApi import pyperclip import datetime from random import choice import requests import threading import time Юзер агенты Затем нам понадобится немного рандомных юзерагентов, я взял их с последней модели ксяоми user_agents = [ 'Mozilla/5.0 (Linux; Android 11; 21061179AG Build/RP1A.200720.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/94.0.4606.85 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/361.0.0.39.115;]', 'Mozilla/5.0 (Linux; Android 11; 22011169UY Build/RP1A.200720.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/104.0.5112.97 Mobile Safari/537.36 [FB_IAB/Orca-Android;FBAV/376.1.0.25.106;]', 'Mozilla/5.0 (Linux; Android 11; 21121159SG Build/RP1A.200720.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/94.0.4606.85 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/381.0.0.29.105;]', 'Mozilla/5.0 (Linux; Android 11; 21061149AG) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Mobile Safari/537.36', 'Mozilla/5.0 (Linux; Android 12; 21121139SG) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Mobile Safari/537.36', ] Python user_agents = [ 'Mozilla/5.0 (Linux; Android 11; 21061179AG Build/RP1A.200720.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/94.0.4606.85 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/361.0.0.39.115;]', 'Mozilla/5.0 (Linux; Android 11; 22011169UY Build/RP1A.200720.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/104.0.5112.97 Mobile Safari/537.36 [FB_IAB/Orca-Android;FBAV/376.1.0.25.106;]', 'Mozilla/5.0 (Linux; Android 11; 21121159SG Build/RP1A.200720.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/94.0.4606.85 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/381.0.0.29.105;]', 'Mozilla/5.0 (Linux; Android 11; 21061149AG) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Mobile Safari/537.36', 'Mozilla/5.0 (Linux; Android 12; 21121139SG) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Mobile Safari/537.36', ] Первые функции Зачем нужна переменная flag я объясню чуть позже. В блоке трай/экзепт мы открываем наш файл group.txt и сохраняем содержимое в переменную group Файл group.txt нужен для того чтобы не вписывать каждый раз список групп flag = True try: file = open('group.txt', mode='r', encoding='utf-8') group = file.read() except: group = '7777777\n8888888\n9999999' # Если файла group.txt нету, группы возьмутся от сюда Python flag = True try: file = open('group.txt', mode='r', encoding='utf-8') group = file.read() except: group = '7777777\n8888888\n9999999' # Если файла group.txt нету, группы возьмутся от сюда Функции которые помогут работать нам с буфером обмена tkinter очень неадекватно относится к буферу при русской раскладке, поэтому мы импортируем дополнительную библиотеку и биндим каждое поле ввода на правую кнопку мыши, при нажатии на которую в поле копируетя содержимое буфера def touch_password(event): input_password.insert(0, pyperclip.paste()) def touch_list_group(event): input_list_group.insert(1.0, pyperclip.paste() + '\n') def touch_text(event): input_text.insert(1.0, pyperclip.paste()) def touch_photo(event): input_photo.insert(0, pyperclip.paste()) Python def touch_password(event): input_password.insert(0, pyperclip.paste()) def touch_list_group(event): input_list_group.insert(1.0, pyperclip.paste() + '\n') def touch_text(event): input_text.insert(1.0, pyperclip.paste()) def touch_photo(event): input_photo.insert(0, pyperclip.paste()) Получаем сессию ВКонтакте Чтобы не возиться с токенами, мы сделаем функцию авторизации по логину и паролю, по моему скромному мнению авторизация по логин:пасс более привычна для человека работающего с аккаунтами. def get_token(login, password): session = requests.Session() user_agent = choice(user_agents) # выбераем рандомный ЮА из нашего списка session.headers.update({'User-agent': user_agent}) # перезаписываем дефолтный ЮА response = requests.get( f'https://oauth.vk.com/token?grant_type=password&client_id=2274003&client_secret=hHbZxrka2uZ6jB1inYsH&username={login}&password={password}&v=5.131&2fa_supported=1' ) if 'error_description' in response.json(): return False # если логин и пароль неверные возвращаем False token = response.json()['access_token'] vk_session = VkApi(token=token) # авторизовываемся по токену vk_session.http.headers['User-agent'] = user_agent # вставляем юзерагент return vk_session # возвращаем авторизованную сессию Python def get_token(login, password): session = requests.Session() user_agent = choice(user_agents) # выбераем рандомный ЮА из нашего списка session.headers.update({'User-agent': user_agent}) # перезаписываем дефолтный ЮА response = requests.get( f'https://oauth.vk.com/token?grant_type=password&client_id=2274003&client_secret=hHbZxrka2uZ6jB1inYsH&username={login}&password={password}&v=5.131&2fa_supported=1' ) if 'error_description' in response.json(): return False # если логин и пароль неверные возвращаем False token = response.json()['access_token'] vk_session = VkApi(token=token) # авторизовываемся по токену vk_session.http.headers['User-agent'] = user_agent # вставляем юзерагент return vk_session # возвращаем авторизованную сессию Функции для работы с потоками Две функции, одна создаёт поток, вторая его глушит с помощью переменной flag которую мы определили выше. Потоки необходимы т.к. tkinter в основном потоке поддерживает и обновляет виджеты а так же прослушивает события. def start_action(): btn_start.config(state=tk.DISABLED) # делаем кнопку неактивной thread = threading.Thread(target=started) # поток print(thread.name) # выводим имя потока thread.start() # запускаем поток def stop_action(): global flag # указываем, что мы собираемся работать с глобальной переменной flag = False # передаём сигнал в поток о завершении Python def start_action(): btn_start.config(state=tk.DISABLED) # делаем кнопку неактивной thread = threading.Thread(target=started) # поток print(thread.name) # выводим имя потока thread.start() # запускаем поток def stop_action(): global flag # указываем, что мы собираемся работать с глобальной переменной flag = False # передаём сигнал в поток о завершении Функция очистки полей Я поленился её писать подумав о её ненужности, но шаблончик оставил если вдруг прижмёт def cleaner(): input_logs.delete(1.0, tk.END) # эта функция очистки всех полей, я поленился её делать Python def cleaner(): input_logs.delete(1.0, tk.END) # эта функция очистки всех полей, я поленился её делать А вот и мозги нашего приложения Самая основная функция. Сначала получаем активную сессию ВКонтакте с помощью функции которую мы написали выше. Далее создаём пустой словарь, в нём мы будем хранить айди группы и айди последней записи вконтакте. Затем первым циклом проходимся по группам и наполняем наш словарь данными, после этого запускаем второй (бесконечный) цикл, им мы будем мониторить обновление постов в группах и при условии, что ид последней записи группы не равен иду в нашем словаре мы будем отправлять соответствующий текст, после чего перезапишем ид последней записи в нашем словаре def started(): account = input_password.get() # получаем аккаунт list_group = input_list_group.get(1.0, tk.END) # получаем список групп text = input_text.get(1.0, tk.END) # получаем текст рассылки attachment = input_photo.get() # вложение login, password = account.split(':') vk_session = get_token(login, password) time.sleep(2) check_list_group = {} # создаём пустой словарь for group in list_group.rstrip().split('\n'): print(group) result = vk_session.method('wall.get', {'owner_id': f'-{group.strip()}', 'count': 1}) print(result) id_group = result["items"][0]["id"] input_logs.insert(1.0, f'Группа {group}, ид последней записи {id_group}\nВремя {datetime.datetime.fromtimestamp(result["items"][0]["date"])}' + '\n' + ' ******* ' + '\n') check_list_group[group] = id_group time.sleep(6) root.update() time.sleep(5) while True: for group in check_list_group: print(group) check_id = vk_session.method('wall.get', {'owner_id': f'-{group}', 'count': 1}) id_post = check_id["items"][0]["id"] time.sleep(7) if check_list_group[group] != id_post: # проверяем на наличие новых постов vk_session.method('wall.createComment', {'owner_id': f'-{group}', 'post_id': id_post, 'message': text.strip(), 'attachments': attachment}) check_list_group[group] = id_post # перезаписываем ид последней записи input_logs.insert(1.0, f'Комментарий в группе\nhttps://vk.com/club{group}\nуспешно оставлен!!\n ******* \n') root.update() # это обновляет наш GUI оно в принципе не нужно, но у меня почему-то зависало поле отправки time.sleep(7) # после отправки сообщения, отдыхаем 7 секунд и в бой!! time.sleep(6) if flag == False: break # брикаем функцию btn_start.config(state=tk.NORMAL) # нормализуем кнопку Python def started(): account = input_password.get() # получаем аккаунт list_group = input_list_group.get(1.0, tk.END) # получаем список групп text = input_text.get(1.0, tk.END) # получаем текст рассылки attachment = input_photo.get() # вложение login, password = account.split(':') vk_session = get_token(login, password) time.sleep(2) check_list_group = {} # создаём пустой словарь for group in list_group.rstrip().split('\n'): print(group) result = vk_session.method('wall.get', {'owner_id': f'-{group.strip()}', 'count': 1}) print(result) id_group = result["items"][0]["id"] input_logs.insert(1.0, f'Группа {group}, ид последней записи {id_group}\nВремя {datetime.datetime.fromtimestamp(result["items"][0]["date"])}' + '\n' + ' ******* ' + '\n') check_list_group[group] = id_group time.sleep(6) root.update() time.sleep(5) while True: for group in check_list_group: print(group) check_id = vk_session.method('wall.get', {'owner_id': f'-{group}', 'count': 1}) id_post = check_id["items"][0]["id"] time.sleep(7) if check_list_group[group] != id_post: # проверяем на наличие новых постов vk_session.method('wall.createComment', {'owner_id': f'-{group}', 'post_id': id_post, 'message': text.strip(), 'attachments': attachment}) check_list_group[group] = id_post # перезаписываем ид последней записи input_logs.insert(1.0, f'Комментарий в группе\nhttps://vk.com/club{group}\nуспешно оставлен!!\n ******* \n') root.update() # это обновляет наш GUI оно в принципе не нужно, но у меня почему-то зависало поле отправки time.sleep(7) # после отправки сообщения, отдыхаем 7 секунд и в бой!! time.sleep(6) if flag == False: break # брикаем функцию btn_start.config(state=tk.NORMAL) # нормализуем кнопку На этом пока всё, самой интересное я оставил на десерт! Во второй части мы займёмся исключительно самим GUI Выглядеть он будет примерно так =)) Для самых нетерпеливых ссылка на готовый продукт!! Всем удачного кодинга и до скорых встреч =)) Ссылка на вторую часть