Commit e01f31c2 authored by root's avatar root

Refactor backend, implement external unlocking, use argument instead of env variable for run script

parent 776b7673
...@@ -22,11 +22,19 @@ def get_nested(obj, path, default=None): ...@@ -22,11 +22,19 @@ def get_nested(obj, path, default=None):
obj = obj[p] obj = obj[p]
return obj return obj
def is_error(result, code):
return isinstance(result.get("errors", None), list) and len([x for x in result["errors"] if x.get("code", None) == code]) > 0
account_sessions = [] account_sessions = []
account_index = 0 account_index = 0
log_file = None log_file = None
debug_file = None debug_file = None
def next_session():
sessions = sorted([s for s in account_sessions if not s.locked], key=lambda s:-s.remaining)
if len(sessions) > 0:
return sessions[0]
class TwitterSession: class TwitterSession:
_auth = "AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA" _auth = "AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA"
_user_url = "https://api.twitter.com/graphql/SEn6Mq-OakvVOT1CJqUO2A/UserByScreenName?variables=" _user_url = "https://api.twitter.com/graphql/SEn6Mq-OakvVOT1CJqUO2A/UserByScreenName?variables="
...@@ -43,9 +51,10 @@ class TwitterSession: ...@@ -43,9 +51,10 @@ class TwitterSession:
# rate limit monitoring # rate limit monitoring
self.limit = -1 self.limit = -1
self.remaining = -1 self.remaining = 180
self.reset = -1 self.reset = -1
self.overshot = -1 self.overshot = -1
self.locked = False
# session user's @username # session user's @username
# this stays `None` for guest sessions # this stays `None` for guest sessions
...@@ -70,6 +79,8 @@ class TwitterSession: ...@@ -70,6 +79,8 @@ class TwitterSession:
self._session.cookie_jar.load(cookie_file) self._session.cookie_jar.load(cookie_file)
login_required = False login_required = False
store_cookies = True
if login_required: if login_required:
async with self._session.get("https://twitter.com/login", headers=self._headers) as r: async with self._session.get("https://twitter.com/login", headers=self._headers) as r:
login_page = await r.text() login_page = await r.text()
...@@ -80,11 +91,13 @@ class TwitterSession: ...@@ -80,11 +91,13 @@ class TwitterSession:
form_data["session[password]"] = password form_data["session[password]"] = password
form_data["remember_me"] = "1" form_data["remember_me"] = "1"
async with self._session.post('https://twitter.com/sessions', data=form_data, headers=self._headers) as r: async with self._session.post('https://twitter.com/sessions', data=form_data, headers=self._headers) as r:
await r.text() response = await r.text()
if str(r.url) == "https://twitter.com/": if str(r.url) == "https://twitter.com/":
log("Login of %s successful" % username) log("Login of %s successful" % username)
else: else:
log("Error logging in %s" % username) store_cookies = False
log("Error logging in %s (%s)" % (username, r.url))
debug("ERROR PAGE\n" + response)
else: else:
async with self._session.get('https://twitter.com', headers=self._headers) as r: async with self._session.get('https://twitter.com', headers=self._headers) as r:
await r.text() await r.text()
...@@ -93,7 +106,7 @@ class TwitterSession: ...@@ -93,7 +106,7 @@ class TwitterSession:
self.username = username self.username = username
if cookie_file is not None: if cookie_file is not None and store_cookies:
self._session.cookie_jar.save(cookie_file) self._session.cookie_jar.save(cookie_file)
else: else:
...@@ -139,8 +152,10 @@ class TwitterSession: ...@@ -139,8 +152,10 @@ class TwitterSession:
self.set_csrf_header() self.set_csrf_header()
if self.username is not None: if self.username is not None:
self.monitor_rate_limit(r.headers) self.monitor_rate_limit(r.headers)
if retry_csrf and isinstance(result.get("errors", None), list) and len([x for x in result["errors"] if x.get("code", None) == 353]): if retry_csrf and is_error(result, 353):
return await self.tweet_raw(tweet_id, count, cursor, False) return await self.tweet_raw(tweet_id, count, cursor, False)
if is_error(result, 326):
self.locked = True
return result return result
def monitor_rate_limit(self, headers): def monitor_rate_limit(self, headers):
...@@ -253,7 +268,10 @@ class TwitterSession: ...@@ -253,7 +268,10 @@ class TwitterSession:
global account_sessions global account_sessions
global account_index global account_index
reference_session = account_sessions[account_index % len(account_sessions)] reference_session = next_session()
if reference_session is None:
return
account_index += 1 account_index += 1
before_barrier = await reference_session.tweet_raw(replied_to_id, 1000) before_barrier = await reference_session.tweet_raw(replied_to_id, 1000)
...@@ -396,14 +414,28 @@ def log(message): ...@@ -396,14 +414,28 @@ def log(message):
else: else:
print(message) print(message)
@routes.get('/.stats')
async def stats(request):
text = "Locked Limit Remaining Reset"
for session in account_sessions:
text += "\n%6d %5d %9d %5d" % (int(session.locked), session.limit, session.remaining, session.reset - int(time.time()))
return web.Response(text=text)
@routes.get('/.unlocked/{screen_name}')
async def unlocked(request):
screen_name = request.match_info['screen_name']
text = "Not unlocked"
for session in account_sessions:
if session.username.lower() != screen_name.lower():
continue
session.locked = False
text = "Unlocked"
return web.Response(text=text)
@routes.get('/{screen_name}') @routes.get('/{screen_name}')
async def hello(request): async def api(request):
screen_name = request.match_info['screen_name'] screen_name = request.match_info['screen_name']
if screen_name == '.stats':
text = "Limit Remaining Reset"
for session in account_sessions:
text += "\n%5d %9d %5d" % (session.limit, session.remaining, session.reset - int(time.time()))
return web.Response(text=text)
session = TwitterSession() session = TwitterSession()
result = await session.test(screen_name) result = await session.test(screen_name)
log(json.dumps(result) + '\n') log(json.dumps(result) + '\n')
......
#/usr/bin/env bash #/usr/bin/env bash
if [ "$PYTHON_ENV" != 'production' ] && [ "$PYTHON_ENV" != 'development' ]; then if [ "$1" != 'production' ] && [ "$1" != 'development' ]; then
echo "Please provide a PYTHON_ENV value of 'production' or 'development'" echo "Please provide 'production' or 'development' as first argument"
echo "e.g. $ PYTHON_ENV=development $0" echo "e.g. $ $0 development"
exit exit
fi fi
EXPECTED_ENV_FILE="./.env.$PYTHON_ENV" EXPECTED_ENV_FILE="./.env.$1"
if [ ! -f $EXPECTED_ENV_FILE ]; then if [ ! -f $EXPECTED_ENV_FILE ]; then
echo "Please provide a configuration file {$EXPECTED_ENV_FILE}!" echo "Please provide a configuration file {$EXPECTED_ENV_FILE}!"
fi fi
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment