basically.... yea
This commit is contained in:
parent
35fbb4b695
commit
08c231209c
File diff suppressed because it is too large
Load Diff
161
bot/main.py
161
bot/main.py
|
|
@ -1,5 +1,156 @@
|
|||
- get chats page
|
||||
- for each
|
||||
- if seen_at is less than latest[created_at]
|
||||
- get token url from api
|
||||
- respond to that user
|
||||
import asyncio
|
||||
import aiohttp
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
from typing import Optional, Dict, Any
|
||||
from dotenv import load_dotenv
|
||||
import urllib.parse
|
||||
import re
|
||||
|
||||
load_dotenv()
|
||||
|
||||
SKETCHERS_UNITED_SESSION = os.environ.get('SKETCHERS_UNITED_SESSION')
|
||||
REMEMBER_WEB = os.environ.get('REMEMBER_WEB')
|
||||
TARGET_URL = 'https://sketchersunited.org/chats'
|
||||
API_PASSWORD = os.environ.get('API_PASSWORD')
|
||||
XSRF_TOKEN = os.environ.get('XSRF_TOKEN')
|
||||
|
||||
def get_session_cookie_header() -> Optional[Dict[str, str]]:
|
||||
if not SKETCHERS_UNITED_SESSION or not REMEMBER_WEB:
|
||||
print("Missing required session or remember_web environment variables.", file=sys.stderr)
|
||||
return None
|
||||
|
||||
cookies_to_send = []
|
||||
cookies_to_send.append(f"sketchers_united_session={SKETCHERS_UNITED_SESSION}")
|
||||
cookies_to_send.append(f"remember_web_59ba36addc2b2f9401580f014c7f58ea4e30989d={REMEMBER_WEB}")
|
||||
|
||||
if XSRF_TOKEN:
|
||||
cookies_to_send.append(f"XSRF-TOKEN={XSRF_TOKEN}")
|
||||
|
||||
cookie_header = "; ".join(cookies_to_send)
|
||||
|
||||
return {
|
||||
'Cookie': cookie_header,
|
||||
'Accept': 'application/json',
|
||||
'User-Agent': 'usernames chat checking bot',
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
|
||||
def get_post_headers(xsrf_token: str) -> Dict[str, str]:
|
||||
return {
|
||||
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:133.0) Gecko/20100101 Firefox/133.0',
|
||||
'Accept': 'application/json, text/plain, */*',
|
||||
'Accept-Language': 'en-US,en;q=0.5',
|
||||
'X-XSRF-TOKEN': xsrf_token,
|
||||
'Sec-GPC': '1',
|
||||
'Sec-Fetch-Dest': 'empty',
|
||||
'Sec-Fetch-Mode': 'cors',
|
||||
'Sec-Fetch-Site': 'same-origin',
|
||||
'Priority': 'u=0',
|
||||
}
|
||||
|
||||
async def make_new_json_request(user_id: int):
|
||||
url = f'http://localhost/api/token/{user_id}'
|
||||
data = {
|
||||
'password': API_PASSWORD
|
||||
}
|
||||
|
||||
headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
}
|
||||
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.post(url, json=data, headers=headers) as response:
|
||||
response_text = await response.text()
|
||||
return response_text
|
||||
|
||||
async def post_chat_update(session: aiohttp.ClientSession, chat_object: Dict[str, Any], xsrf_token: str):
|
||||
pattern = r'/(\d+)/'
|
||||
match = re.search(pattern, chat_object.get('icon_url'))
|
||||
|
||||
token = await make_new_json_request(match.group(1))
|
||||
|
||||
form_data = aiohttp.FormData()
|
||||
form_data.add_field('text', f"""You've signed up for the Secret Sketchers event, your link is http://localhost/profile/{token} - it is private and should only be used by you.
|
||||
\nDon't want to be in it anymore? Go to http://localhost/withdraw/{token} - note that withdrawing is permanent and you cannot re-enter the event.""")
|
||||
|
||||
headers = get_post_headers(xsrf_token)
|
||||
|
||||
try:
|
||||
cookie_headers = get_session_cookie_header()
|
||||
if cookie_headers:
|
||||
headers['Cookie'] = cookie_headers['Cookie']
|
||||
|
||||
async with session.post(
|
||||
f"{TARGET_URL}/{chat_object.get('id')}/messages",
|
||||
data=form_data,
|
||||
headers=headers
|
||||
) as response:
|
||||
if response.status not in [200, 201]:
|
||||
text = await response.text()
|
||||
print(f" Status: {response.status}. Response: {text}", file=sys.stderr)
|
||||
except aiohttp.ClientError as e:
|
||||
print(f"-> POST ERROR: Client error during update for chat ID {chat_object.get('id', 'N/A')}: {e}", file=sys.stderr)
|
||||
except Exception as e:
|
||||
print(f"-> POST ERROR: Unexpected error during update for chat ID {chat_object.get('id', 'N/A')}: {e}", file=sys.stderr)
|
||||
|
||||
|
||||
|
||||
async def process_chats():
|
||||
global XSRF_TOKEN
|
||||
|
||||
async with aiohttp.ClientSession() as session:
|
||||
headers = get_session_cookie_header()
|
||||
if not headers:
|
||||
return
|
||||
|
||||
async with session.get(TARGET_URL, headers=headers) as response:
|
||||
if response.status != 200:
|
||||
print(f"failed: {response.status}", file=sys.stderr)
|
||||
return
|
||||
|
||||
try:
|
||||
chat_data_array = await response.json()
|
||||
if not isinstance(chat_data_array, list):
|
||||
print("not json", file=sys.stderr)
|
||||
return
|
||||
|
||||
except aiohttp.ContentTypeError:
|
||||
print("also not json", file=sys.stderr)
|
||||
return
|
||||
|
||||
fresh_xsrf_token = None
|
||||
for cookie in session.cookie_jar:
|
||||
if cookie.key == "XSRF-TOKEN":
|
||||
fresh_xsrf_token = urllib.parse.unquote(cookie.value)
|
||||
break
|
||||
|
||||
XSRF_TOKEN = fresh_xsrf_token
|
||||
|
||||
for index, chat_object in enumerate(chat_data_array):
|
||||
if(chat_object.get('type') == 'private'):
|
||||
seen_at_value = chat_object.get('seen_at')
|
||||
is_unread = False
|
||||
|
||||
try:
|
||||
if isinstance(seen_at_value, dict):
|
||||
is_unread = True
|
||||
# print(f"Chat {index}: Status: DICT (New Chat) -> Unread: True")
|
||||
else:
|
||||
latest_created_at = chat_object.get('latest', {}).get('created_at', 0)
|
||||
seen_at_int = int(seen_at_value) if seen_at_value is not None else 0
|
||||
|
||||
is_unread = seen_at_int < latest_created_at
|
||||
# print(f"Chat {index}: Seen at ({seen_at_int}) < Latest message ({latest_created_at}) -> Unread: {is_unread}")
|
||||
|
||||
except (AttributeError, TypeError, ValueError) as e:
|
||||
is_unread = False
|
||||
|
||||
if is_unread:
|
||||
await post_chat_update(session, chat_object, fresh_xsrf_token)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(process_chats())
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ $cancelEditingSubmission = function ()
|
|||
</div>
|
||||
|
||||
<div class="other-content">
|
||||
<h2> Are you done? </h2>
|
||||
<h2> Are you done? </h2>
|
||||
<p>You will be able to link to your gift below once submissions are accepted on 22nd December.</p>
|
||||
<small style="color:rgba(255,255,255,0.5)">submissions will be accepted up until 5th of january but before then is much more appreciated!</small>
|
||||
|
||||
|
|
@ -204,14 +204,17 @@ $cancelEditingSubmission = function ()
|
|||
@elseif($participant->desperate)
|
||||
<p>You're in a bind!</p>
|
||||
@else
|
||||
<p>You haven't been assigned anyone.</p>
|
||||
<p>You haven't been assigned anyone yet. Assignments will be made on DATE</p>
|
||||
@endif
|
||||
</div>
|
||||
<div class="other-content">
|
||||
<a
|
||||
href="/withdraw/{{$token}}"
|
||||
>
|
||||
Withdraw from Secret Sketchers...
|
||||
>
|
||||
Withdraw from Secret Sketchers...?
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@endif
|
||||
|
||||
<style>
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ $withdraw = function ()
|
|||
|
||||
<div>
|
||||
<h1>Withdraw from the event?</h1>
|
||||
<p>Withdrawing is permanent, once you withdraw you cannot rejoin.</p>
|
||||
<button
|
||||
wire:click="confirmWithdrawal"
|
||||
class=""
|
||||
|
|
|
|||
Loading…
Reference in New Issue