Как выглядит Как настроить: Сюда коммент после выдачи личного Сюда токен Сюда свой ник доп настройки: black_list - туда пишешь ники, кому скрипт не будет выдавать личные likes_lim - дает личные от X симпатий (ставишь 50, новокеки с 49 симпами пролетают и не лутают) скачать тампермонки https://chromewebstore.google.com/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo Вставить код (тамперманки может работать криво, но работает): // ==UserScript== // @name Lolz.guru Auto Responder (Improved) // @namespace http://tampermonkey.net/ // @version 1.3 // @description Автоответчик для Lolz.guru с исправлениями ошибок // @author Your Name // @match https://lolz.live/* // @match https://lolz.guru/* // @match https://zelenka.guru/* // @grant GM_xmlhttpRequest // @grant GM_setValue // @grant GM_getValue // @grant GM_notification // @connect prod-api.zelenka.guru // @connect api.lolz.live // @connect lolz.guru // @connect zelenka.guru // ==/UserScript== (function() { 'use strict'; class Lolz { constructor() { this.USERNAME = ""; this.BLACK_LIST = []; this.LIKES_LIM = 0; this.TOKEN = ""; this.processedMessages = GM_getValue('processedMessages', {}); this.otherMessagesLog = GM_getValue('otherMessagesLog', ""); this.isRunning = true; } apiRequest(method, url, data = null) { return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: method, url: url, headers: { 'Authorization': 'Bearer ' + this.TOKEN, 'Content-Type': 'application/json' }, data: data ? JSON.stringify(data) : null, onload: (response) => { if (response.status >= 200 && response.status < 300) { try { resolve(JSON.parse(response.responseText)); } catch (e) { resolve(response.responseText); } } else { reject(new Error(`API error: ${response.status}`)); } }, onerror: (error) => { reject(error); } }); }); } async getConversations() { try { const response = await this.apiRequest('GET', 'https://prod-api.zelenka.guru/conversations'); return response.conversations || []; } catch (e) { console.error('Error getting conversations:', e); return []; } } async getThreadInfo(tid) { try { return await this.apiRequest('GET', `https://prod-api.zelenka.guru/threads/${tid}`); } catch (e) { console.error('Error getting thread info:', e); return null; } } async getUser(link) { try { return await this.apiRequest('GET', link); } catch (e) { console.error('Error getting user:', e); return { user: {} }; } } async sendMsg(conversationId, msg) { const data = { 'conversation_id': conversationId, 'message_body': msg }; try { return await this.apiRequest('POST', 'https://prod-api.zelenka.guru/conversation-messages', data); } catch (e) { console.error('Error sending message:', e); return null; } } async getAllMessages(conversation) { try { if (!conversation.links || !conversation.links.messages) { return { messages: [] }; } const response = await this.apiRequest('GET', conversation.links.messages); return { messages: response.messages || [] }; } catch (e) { console.error('Error getting messages:', e); return { messages: [] }; } } clean(rawHtml) { return rawHtml.replace(/<[^>]*>/g, '').replace(/Нажмите, чтобы раскрыть\.\.\./g, ''); } async getThread(m) { try { const threadId = m.message_body; const match = threadId.match(/threads\/(\d+)/); if (!match) return null; const threadInfo = await this.getThreadInfo(match[1]); if (!threadInfo || !threadInfo.thread) return null; const thread = threadInfo.thread; await this.delay(500); const creator = thread.creator_username; if (creator !== this.USERNAME && !this.BLACK_LIST.includes(creator)) { return null; } const text = thread.first_post.post_body_html; if (!text.includes('quoteContainer hideContainer')) { return null; } const quotePart = text.split('<blockquote class="quoteContainer hideContainer">')[1] .split('</blockquote>')[0]; return this.clean(quotePart); } catch (e) { console.error('Error processing thread:', e); return null; } } delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } async logOtherMessage(message) { try { const messageId = message.message_id.toString(); if (this.otherMessagesLog.includes(messageId)) { return; } const newEntry = `Username: ${message.creator_username}\n` + `Message: ${message.message_body}\n` + `message_id: ${messageId}\n` + "________\n"; this.otherMessagesLog = newEntry + this.otherMessagesLog; GM_setValue('otherMessagesLog', this.otherMessagesLog); } catch (e) { console.error('Error logging message:', e); } } async processMessage(elem, message) { if (this.processedMessages[message.message_id]) return; if (message.message_body.match(/threads\/(\d+)/)) { try { const userLink = elem.links?.creator || elem.first_message?.links?.creator || message.links?.creator; if (!userLink) { console.log('No creator link found for message', message.message_id); return; } const user = await this.getUser(userLink); await this.delay(500); if ((user.user?.user_like_count || 100) < this.LIKES_LIM) { return; } const msg = await this.getThread(message); await this.delay(500); if (!msg) return; // Отправка основного сообщения console.log('Sending message to', user.user?.username || "hidden"); await this.sendMsg(elem.conversation_id, msg); await this.delay(10000); // Отправка дополнительного сообщения const thanksMsg = "Спасибо, что зашел ко мне в тему. Отпиши в тему, что получил личный и обязательно свое мнение/впечатление о теме (необязательно положительное)"; await this.sendMsg(elem.conversation_id, thanksMsg); await this.delay(10000); this.processedMessages[message.message_id] = true; GM_setValue('processedMessages', this.processedMessages); } catch (e) { console.error('Error processing thread message:', e); } } else { await this.logOtherMessage(message); this.processedMessages[message.message_id] = true; GM_setValue('processedMessages', this.processedMessages); } } async pool() { if (!this.isRunning) return; try { const conversations = await this.getConversations(); await this.delay(500); for (const conversation of conversations) { try { const messagesData = await this.getAllMessages(conversation); const messages = messagesData.messages; await this.delay(500); let toDo = []; for (let i = 0; i < Math.min(5, messages.length); i++) { const message = messages[i]; if (message.creator_username === this.USERNAME) break; toDo.push(message); } toDo.reverse(); for (const message of toDo) { await this.processMessage(conversation, message); } await this.delay(500); } catch (e) { console.error('Error processing conversation:', e); } } console.log("Сплю 120 сек"); await this.delay(120000); this.pool(); } catch (e) { console.error('Pool error:', e); await this.delay(10000); this.pool(); } } stop() { this.isRunning = false; } } // Запуск скрипта const lol = new Lolz(); lol.pool(); // Добавляем возможность остановки скрипта через консоль window.LolzAutoResponder = lol; })(); Код // ==UserScript== // @name Lolz.guru Auto Responder (Improved) // @namespace http://tampermonkey.net/ // @version 1.3 // @description Автоответчик для Lolz.guru с исправлениями ошибок // @author Your Name // @match https://lolz.live/* // @match https://lolz.guru/* // @match https://zelenka.guru/* // @grant GM_xmlhttpRequest // @grant GM_setValue // @grant GM_getValue // @grant GM_notification // @connect prod-api.zelenka.guru // @connect api.lolz.live // @connect lolz.guru // @connect zelenka.guru // ==/UserScript== (function() { 'use strict'; class Lolz { constructor() { this.USERNAME = ""; this.BLACK_LIST = []; this.LIKES_LIM = 0; this.TOKEN = ""; this.processedMessages = GM_getValue('processedMessages', {}); this.otherMessagesLog = GM_getValue('otherMessagesLog', ""); this.isRunning = true; } apiRequest(method, url, data = null) { return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: method, url: url, headers: { 'Authorization': 'Bearer ' + this.TOKEN, 'Content-Type': 'application/json' }, data: data ? JSON.stringify(data) : null, onload: (response) => { if (response.status >= 200 && response.status < 300) { try { resolve(JSON.parse(response.responseText)); } catch (e) { resolve(response.responseText); } } else { reject(new Error(`API error: ${response.status}`)); } }, onerror: (error) => { reject(error); } }); }); } async getConversations() { try { const response = await this.apiRequest('GET', 'https://prod-api.zelenka.guru/conversations'); return response.conversations || []; } catch (e) { console.error('Error getting conversations:', e); return []; } } async getThreadInfo(tid) { try { return await this.apiRequest('GET', `https://prod-api.zelenka.guru/threads/${tid}`); } catch (e) { console.error('Error getting thread info:', e); return null; } } async getUser(link) { try { return await this.apiRequest('GET', link); } catch (e) { console.error('Error getting user:', e); return { user: {} }; } } async sendMsg(conversationId, msg) { const data = { 'conversation_id': conversationId, 'message_body': msg }; try { return await this.apiRequest('POST', 'https://prod-api.zelenka.guru/conversation-messages', data); } catch (e) { console.error('Error sending message:', e); return null; } } async getAllMessages(conversation) { try { if (!conversation.links || !conversation.links.messages) { return { messages: [] }; } const response = await this.apiRequest('GET', conversation.links.messages); return { messages: response.messages || [] }; } catch (e) { console.error('Error getting messages:', e); return { messages: [] }; } } clean(rawHtml) { return rawHtml.replace(/<[^>]*>/g, '').replace(/Нажмите, чтобы раскрыть\.\.\./g, ''); } async getThread(m) { try { const threadId = m.message_body; const match = threadId.match(/threads\/(\d+)/); if (!match) return null; const threadInfo = await this.getThreadInfo(match[1]); if (!threadInfo || !threadInfo.thread) return null; const thread = threadInfo.thread; await this.delay(500); const creator = thread.creator_username; if (creator !== this.USERNAME && !this.BLACK_LIST.includes(creator)) { return null; } const text = thread.first_post.post_body_html; if (!text.includes('quoteContainer hideContainer')) { return null; } const quotePart = text.split('<blockquote class="quoteContainer hideContainer">')[1] .split('</blockquote>')[0]; return this.clean(quotePart); } catch (e) { console.error('Error processing thread:', e); return null; } } delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } async logOtherMessage(message) { try { const messageId = message.message_id.toString(); if (this.otherMessagesLog.includes(messageId)) { return; } const newEntry = `Username: ${message.creator_username}\n` + `Message: ${message.message_body}\n` + `message_id: ${messageId}\n` + "________\n"; this.otherMessagesLog = newEntry + this.otherMessagesLog; GM_setValue('otherMessagesLog', this.otherMessagesLog); } catch (e) { console.error('Error logging message:', e); } } async processMessage(elem, message) { if (this.processedMessages[message.message_id]) return; if (message.message_body.match(/threads\/(\d+)/)) { try { const userLink = elem.links?.creator || elem.first_message?.links?.creator || message.links?.creator; if (!userLink) { console.log('No creator link found for message', message.message_id); return; } const user = await this.getUser(userLink); await this.delay(500); if ((user.user?.user_like_count || 100) < this.LIKES_LIM) { return; } const msg = await this.getThread(message); await this.delay(500); if (!msg) return; // Отправка основного сообщения console.log('Sending message to', user.user?.username || "hidden"); await this.sendMsg(elem.conversation_id, msg); await this.delay(10000); // Отправка дополнительного сообщения const thanksMsg = "Спасибо, что зашел ко мне в тему. Отпиши в тему, что получил личный и обязательно свое мнение/впечатление о теме (необязательно положительное)"; await this.sendMsg(elem.conversation_id, thanksMsg); await this.delay(10000); this.processedMessages[message.message_id] = true; GM_setValue('processedMessages', this.processedMessages); } catch (e) { console.error('Error processing thread message:', e); } } else { await this.logOtherMessage(message); this.processedMessages[message.message_id] = true; GM_setValue('processedMessages', this.processedMessages); } } async pool() { if (!this.isRunning) return; try { const conversations = await this.getConversations(); await this.delay(500); for (const conversation of conversations) { try { const messagesData = await this.getAllMessages(conversation); const messages = messagesData.messages; await this.delay(500); let toDo = []; for (let i = 0; i < Math.min(5, messages.length); i++) { const message = messages[i]; if (message.creator_username === this.USERNAME) break; toDo.push(message); } toDo.reverse(); for (const message of toDo) { await this.processMessage(conversation, message); } await this.delay(500); } catch (e) { console.error('Error processing conversation:', e); } } console.log("Сплю 120 сек"); await this.delay(120000); this.pool(); } catch (e) { console.error('Pool error:', e); await this.delay(10000); this.pool(); } } stop() { this.isRunning = false; } } // Запуск скрипта const lol = new Lolz(); lol.pool(); // Добавляем возможность остановки скрипта через консоль window.LolzAutoResponder = lol; })(); и пайтон версия, которая нраица мне больше, и не имеет багов import sys import requests import time import re from time import sleep class Lolz: USERNAME = "" BLACK_LIST = [] LIKES_LIM = 0 MESSAGES_LIM = 0 TOKEN = "" def __init__(self): self.ses = requests.Session() self.ses.headers['Authorization'] = 'Bearer ' + self.TOKEN try: self.ses.post('https://api.lolz.live/', timeout=10) sleep(.5) except Exception as e: print(f"Ошибка при подключении: {e}") def get_conversations(self): return self.ses.get('https://prod-api.zelenka.guru/conversations', timeout=10).json() def get_thread_info(self, tid): return self.ses.get(f'https://prod-api.zelenka.guru/threads/{tid}', timeout=10).json() def get_thread(self, m): thread_id = m['message_body'] match = re.search(r"threads/(\d+)", thread_id) thread_info = self.get_thread_info(match.group(1))['thread'] sleep(.5) creator = thread_info['creator_username'] if creator != Lolz.USERNAME and creator not in Lolz.BLACK_LIST: return None text = thread_info['first_post']['post_body_html'] if 'quoteContainer hideContainer' not in text: return None text = ''.join( clean(text.split('<blockquote class="quoteContainer hideContainer">')[-1].split( '</blockquote>')[0]).split( 'Нажмите, чтобы раскрыть...')) return text def get_user(self, link): return self.ses.get(link, timeout=10).json() def send_msg(self, user, msg): data = {'conversation_id': user, 'message_body': msg} res = self.ses.post(f'https://prod-api.zelenka.guru/conversation-messages', data=data, timeout=10) return res def get_all_msg(self, perm): return self.ses.get(perm['links']['messages'], timeout=10).json() def clean(raw_html): first_str = re.compile('<.*?>') cleaned_text = re.sub(first_str, '', raw_html) return cleaned_text def pool(): conversations = lol.get_conversations()['conversations'] sleep(.5) for elem in conversations: messages = lol.get_all_msg(elem) sleep(.5) to_do = [] for elem1 in messages['messages'][:5]: if elem1['creator_username'] == Lolz.USERNAME: break to_do.append(elem1) to_do.reverse() for elem1 in to_do: if re.search(r'threads/(\d+)', elem1['message_body']): try: user = lol.get_user(elem['first_message']['links']['creator']) sleep(.5) user_data = user.get('user', {}) # Проверка по количеству лайков if user_data.get('user_like_count', 100) < Lolz.LIKES_LIM: continue # Проверка по количеству сообщений (новая проверка) if user_data.get('message_count', 100) < Lolz.MESSAGES_LIM: continue msg = lol.get_thread(elem1) sleep(.5) if msg is None: continue # Отправка основного сообщения print(msg, user_data.get('username', "hidden"), lol.send_msg(elem['conversation_id'], msg)) time.sleep(10) # Лимит API # Отправка дополнительного сообщения thanks_msg = "Спасибо, что зашел ко мне в тему. Отпиши в тему, что получил личный и обязательно свое мнение/впечатление о теме (необязательно положительное)" print(lol.send_msg(elem['conversation_id'], thanks_msg)) time.sleep(10) # Лимит API except Exception as e: print(e) else: message_id = str(elem1['message_id']) try: with open("log_other_msg.txt", "r", encoding="utf-8") as f: old_data = f.read() except FileNotFoundError: old_data = "" if message_id in old_data: continue new_entry = ( f"Username: {elem1['creator_username']}\n" f"Message: {elem1['message_body']}\n" f"message_id: {message_id}\n" "________\n") with open("log_other_msg.txt", "w", encoding="utf-8") as f: f.write(new_entry + old_data) time.sleep(.5) print("Сплю 120 сек") sleep(120) if __name__=='__main__': lol = Lolz() while True: try: pool() except Exception as e: print(e) time.sleep(10) Python import sys import requests import time import re from time import sleep class Lolz: USERNAME = "" BLACK_LIST = [] LIKES_LIM = 0 MESSAGES_LIM = 0 TOKEN = "" def __init__(self): self.ses = requests.Session() self.ses.headers['Authorization'] = 'Bearer ' + self.TOKEN try: self.ses.post('https://api.lolz.live/', timeout=10) sleep(.5) except Exception as e: print(f"Ошибка при подключении: {e}") def get_conversations(self): return self.ses.get('https://prod-api.zelenka.guru/conversations', timeout=10).json() def get_thread_info(self, tid): return self.ses.get(f'https://prod-api.zelenka.guru/threads/{tid}', timeout=10).json() def get_thread(self, m): thread_id = m['message_body'] match = re.search(r"threads/(\d+)", thread_id) thread_info = self.get_thread_info(match.group(1))['thread'] sleep(.5) creator = thread_info['creator_username'] if creator != Lolz.USERNAME and creator not in Lolz.BLACK_LIST: return None text = thread_info['first_post']['post_body_html'] if 'quoteContainer hideContainer' not in text: return None text = ''.join( clean(text.split('<blockquote class="quoteContainer hideContainer">')[-1].split( '</blockquote>')[0]).split( 'Нажмите, чтобы раскрыть...')) return text def get_user(self, link): return self.ses.get(link, timeout=10).json() def send_msg(self, user, msg): data = {'conversation_id': user, 'message_body': msg} res = self.ses.post(f'https://prod-api.zelenka.guru/conversation-messages', data=data, timeout=10) return res def get_all_msg(self, perm): return self.ses.get(perm['links']['messages'], timeout=10).json() def clean(raw_html): first_str = re.compile('<.*?>') cleaned_text = re.sub(first_str, '', raw_html) return cleaned_text def pool(): conversations = lol.get_conversations()['conversations'] sleep(.5) for elem in conversations: messages = lol.get_all_msg(elem) sleep(.5) to_do = [] for elem1 in messages['messages'][:5]: if elem1['creator_username'] == Lolz.USERNAME: break to_do.append(elem1) to_do.reverse() for elem1 in to_do: if re.search(r'threads/(\d+)', elem1['message_body']): try: user = lol.get_user(elem['first_message']['links']['creator']) sleep(.5) user_data = user.get('user', {}) # Проверка по количеству лайков if user_data.get('user_like_count', 100) < Lolz.LIKES_LIM: continue # Проверка по количеству сообщений (новая проверка) if user_data.get('message_count', 100) < Lolz.MESSAGES_LIM: continue msg = lol.get_thread(elem1) sleep(.5) if msg is None: continue # Отправка основного сообщения print(msg, user_data.get('username', "hidden"), lol.send_msg(elem['conversation_id'], msg)) time.sleep(10) # Лимит API # Отправка дополнительного сообщения thanks_msg = "Спасибо, что зашел ко мне в тему. Отпиши в тему, что получил личный и обязательно свое мнение/впечатление о теме (необязательно положительное)" print(lol.send_msg(elem['conversation_id'], thanks_msg)) time.sleep(10) # Лимит API except Exception as e: print(e) else: message_id = str(elem1['message_id']) try: with open("log_other_msg.txt", "r", encoding="utf-8") as f: old_data = f.read() except FileNotFoundError: old_data = "" if message_id in old_data: continue new_entry = ( f"Username: {elem1['creator_username']}\n" f"Message: {elem1['message_body']}\n" f"message_id: {message_id}\n" "________\n") with open("log_other_msg.txt", "w", encoding="utf-8") as f: f.write(new_entry + old_data) time.sleep(.5) print("Сплю 120 сек") sleep(120) if __name__=='__main__': lol = Lolz() while True: try: pool() except Exception as e: print(e) time.sleep(10)
APT29388, ну реально мужики, я у вас с марта просил допилить коммент при выдаче личных спустя месяц спиздил и доработал сам