# This is an quote and post library for a specific thread in the WarOnline forum. import requests from bs4 import BeautifulSoup import urllib.request as urllib import warnings warnings.filterwarnings("ignore") # Define the login URL and the thread URL login_url = 'https://waronline.org/fora/index.php?login/login' thread_url = 'https://waronline.org/fora/index.php?threads/warbot-playground.17636/' post_url = "https://waronline.org/fora/index.php?threads/warbot-playground.17636/add-reply" # Sending the message (change that!) message = "Test" # Define the login credentials username = 'WarBot' password = 'naP2tion' # Start a session to persist the login cookie across requests session = requests.Session() def compare_pages(url1, url2): #Compares 2 pages and returns True if they are the same return urllib.urlopen(url1).geturl() == urllib.urlopen(url2).geturl() def get_last_page_of_thread(thread_url=thread_url, startingPage=1): #Returns a link to the last page of the thread page = startingPage #Counter lastPage = False while not lastPage: response = requests.get(thread_url + 'page-' + str(page)) if response.status_code == 200: pass # do something (optional) if not compare_pages(thread_url + 'page-' + str(page), thread_url + 'page-' + str(page + 1)): page += 1 else: lastPage = True else: lastPage = True return (thread_url + 'page-' + str(page)) def login(username=username, password=password, thread_url=thread_url): # Log-In to the forum and redirect to thread # Retrieve the login page HTML to get the CSRF token login_page_response = session.get(login_url) soup = BeautifulSoup(login_page_response.text, 'html.parser') csrf_token = soup.find('input', {'name': '_xfToken'})['value'] # Login to the website login_data = { 'login': username, 'password': password, 'remember': '1', '_xfRedirect': thread_url, '_xfToken': csrf_token } response = session.post(login_url, data=login_data) # Check if the login was successful if 'Invalid login' in response.text: print('Login failed!') exit() def post(message=message, thread_url=thread_url, post_url=post_url, quoted_by="",quote_text=""): #Post a message to the forum (with or without the quote quote_source = '3920987' #quoted message source (TBD) if quoted_by: message = f'[QUOTE="{quoted_by}, post: {quote_source}"]{quote_text}[/QUOTE]{message}' # optionally add @{quoted_by} to indent the quoter # Retrieve the thread page HTML response = session.get(thread_url) # Parse the HTML with BeautifulSoup soup = BeautifulSoup(response.text, 'html.parser') # Extract the _xfToken value from the hidden form field xf_token = soup.find('input', {'name': '_xfToken'}).get('value') # Construct the message data for the POST request message_data = { '_xfToken': xf_token, 'message': message, 'attachment_hash': '', 'last_date': '', '_xfRequestUri': post_url, '_xfWithData': '1', '_xfResponseType': 'json' } response = session.post(post_url, data=message_data) # Check if the post was successful if not response.ok: print('Post failed!') exit() print('Post submitted successfully.') def readQuote(thread_url=thread_url, username=username): # Retrieve the content of the specific thread response = session.get(thread_url) html_content = response.content # Parse the HTML content using BeautifulSoup soup = BeautifulSoup(html_content, 'html.parser') # Find all the quotes in the thread quotes = soup.find_all('div', {'class': 'bbWrapper'}) # Check each quote if it contains your name and keep track of the latest one latest_quote = None for quote in quotes: if username in quote.text: latest_quote = quote if latest_quote: reply = latest_quote.text.split("Click to expand...")[-1].replace('\n', ' ').strip() print(reply) if __name__ == '__main__': login(username=username, password=password, thread_url=thread_url) post(message=message, thread_url=thread_url, post_url=post_url,quoted_by='Василий Пупкин',quote_text='Testing the XenForo response mechanism') #readQuote(thread_url=get_last_page_of_thread(thread_url,1)) #! readQuote shall also return the quoted message number. TBD. # The task is to fine the last unanswered quote # Answered quote = there is a post with reply by WarBot # The answer shall be with blockQuote