feat: use public APIs and remove mastodon.py dependency
This commit is contained in:
parent
08403d912b
commit
5a1b8eaee3
5 changed files with 83 additions and 153 deletions
|
@ -5,9 +5,7 @@
|
|||
"title": "Thoughts",
|
||||
"description": "Hand-picked public posts from my social feed",
|
||||
"server": "https://social.ayco.io",
|
||||
"user": "user@mastodon.social",
|
||||
"password": "ultraelectromagneticpassword",
|
||||
"secret_file": "threads-masto-client.secret"
|
||||
"user_id": "0123456789"
|
||||
}
|
||||
},
|
||||
"ATTRIBUTION": {
|
||||
|
|
91
mastodon.py
91
mastodon.py
|
@ -1,91 +0,0 @@
|
|||
from mastodon import Mastodon
|
||||
from . import utils
|
||||
|
||||
session_id = None
|
||||
account_id = None
|
||||
|
||||
def is_public(status):
|
||||
print(status)
|
||||
return status['visibility'] == 'public'
|
||||
|
||||
def get_account_tagged_statuses(app, tag):
|
||||
global account_id
|
||||
mastodon = initialize_client(app)
|
||||
statuses = []
|
||||
try:
|
||||
statuses = mastodon.account_statuses(
|
||||
id=account_id,
|
||||
tagged=tag,
|
||||
exclude_reblogs=True
|
||||
)
|
||||
except:
|
||||
message = f'>>> failed to fetch statuses for ${tag}'
|
||||
raise Exception(message)
|
||||
|
||||
# filter out not public
|
||||
filtered = filter(is_public, statuses)
|
||||
|
||||
return list(map(lambda x: utils.clean_status(x), filtered))
|
||||
|
||||
def initialize_client(app):
|
||||
global session_id
|
||||
global account_id
|
||||
mastodon = None
|
||||
secret = None
|
||||
try:
|
||||
secret_file = open(app['secret_file'], 'r')
|
||||
secret = secret_file.read()
|
||||
except OSError as e:
|
||||
message = '>>> No secret found.'
|
||||
print(message)
|
||||
|
||||
# todo, check if access_token exist in secret_file
|
||||
if secret == None:
|
||||
#...if token does not exist, create app:
|
||||
Mastodon.create_app(
|
||||
app['site_name'],
|
||||
api_base_url = app['server'],
|
||||
to_file = app['secret_file']
|
||||
)
|
||||
try:
|
||||
mastodon = Mastodon(client_id=app['secret_file'])
|
||||
print('>>> Persisted new token!')
|
||||
except:
|
||||
message = '>>> Failed to create masto client token'
|
||||
raise Exception(message)
|
||||
|
||||
else:
|
||||
#... otherwise, reuse
|
||||
try:
|
||||
mastodon = Mastodon(access_token=app['secret_file'])
|
||||
print('>>> Reused persisted token!')
|
||||
except:
|
||||
message = '>>> Persisted token did not work'
|
||||
raise Exception(message)
|
||||
|
||||
if session_id == None:
|
||||
try:
|
||||
session_id = mastodon.log_in(
|
||||
app['user'],
|
||||
app['password'],
|
||||
to_file = app['secret_file']
|
||||
)
|
||||
print('>>> Logged in: ', session_id)
|
||||
except:
|
||||
message = '>>> Failed to get mastodon session'
|
||||
raise Exception(message)
|
||||
else:
|
||||
print('>>> Reused session: ', session_id)
|
||||
|
||||
if account_id == None:
|
||||
try:
|
||||
account = mastodon.me()
|
||||
account_id = account.id
|
||||
print('>>> Set account ID: ', account_id)
|
||||
except:
|
||||
message = '>>> Failed to get mastodon account'
|
||||
raise Exception(message)
|
||||
else:
|
||||
print('>>> Reused account ID:', account_id)
|
||||
|
||||
return mastodon
|
|
@ -3,5 +3,3 @@ requests
|
|||
markdown
|
||||
Flask-Caching
|
||||
aiohttp
|
||||
|
||||
mastodon-py
|
|
@ -6,13 +6,8 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>{{ app.title }} / {{ tag }}</title>
|
||||
<meta name="theme-color" content="#3054bf">
|
||||
{% if threads|length == 1 %}
|
||||
<meta name="description" content="{{ threads[0].summary }}" />
|
||||
<meta property="og:description" content="{{ threads[0].summary }}" />
|
||||
{% else %}
|
||||
<meta name="description" content="{{ app.description }}" />
|
||||
<meta property="og:description" content="{{ app.description }}" />
|
||||
{% endif %}
|
||||
<meta name="author" content="{{ attribution.owner }}" />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:site_name" content="{{ app.site_name }}" />
|
||||
|
|
132
threads.py
132
threads.py
|
@ -4,7 +4,7 @@ from datetime import datetime
|
|||
from .cache import cache
|
||||
import asyncio
|
||||
import aiohttp
|
||||
from . import mastodon, utils
|
||||
from . import utils
|
||||
|
||||
threads = Blueprint('threads', __name__, template_folder='templates', static_folder='static')
|
||||
|
||||
|
@ -45,12 +45,44 @@ thread_ids = [
|
|||
|
||||
###########################################################
|
||||
|
||||
### config
|
||||
def server():
|
||||
return current_app.config['APPS']['threads']['server']
|
||||
|
||||
def get_attribution():
|
||||
return current_app.config['ATTRIBUTION']
|
||||
|
||||
def get_app_config():
|
||||
return current_app.config['APPS']['threads']
|
||||
|
||||
def get_user_id():
|
||||
return current_app.config['APPS']['threads']['user_id']
|
||||
|
||||
### featured tags
|
||||
def get_account_tagged_statuses(tag_name):
|
||||
print(tag_name)
|
||||
id = get_user_id()
|
||||
ser = server()
|
||||
url = f'{ser}/api/v1/accounts/{id}/statuses?exclude_replies=true&tagged={tag_name}'
|
||||
response = requests.get(url)
|
||||
statuses = response.json()
|
||||
statuses = [utils.clean_status(s) for s in statuses]
|
||||
return statuses
|
||||
|
||||
def get_tags_url():
|
||||
id = get_user_id()
|
||||
ser = server()
|
||||
url = f'{ser}/api/v1/accounts/{id}/featured_tags'
|
||||
return url
|
||||
|
||||
def get_featured_tags():
|
||||
url = get_tags_url()
|
||||
response = requests.get(url)
|
||||
tags = response.json()
|
||||
return tags
|
||||
|
||||
|
||||
### middleware
|
||||
@threads.before_request
|
||||
def middleware():
|
||||
# check current year and put ange as attribution
|
||||
|
@ -61,53 +93,7 @@ def middleware():
|
|||
if year != attribution['year']:
|
||||
attribution['current_year'] = year
|
||||
|
||||
@threads.route('/')
|
||||
@cache.cached(timeout=300)
|
||||
async def home():
|
||||
statuses = await fetch_statuses()
|
||||
attribution = get_attribution()
|
||||
app = get_app_config()
|
||||
tags = []
|
||||
|
||||
masto = mastodon.initialize_client(app)
|
||||
|
||||
# List featured hashtags
|
||||
tags = masto.featured_tags()
|
||||
|
||||
return render_template('_home.html', threads=statuses, tags=tags, app=app, attribution=attribution, render_date=datetime.now())
|
||||
|
||||
|
||||
@threads.route('/tag/<path:id>')
|
||||
@cache.cached(timeout=300)
|
||||
async def tag(id):
|
||||
attribution = get_attribution()
|
||||
app = get_app_config()
|
||||
statuses = mastodon.get_account_tagged_statuses(app, id)
|
||||
|
||||
return render_template('_tag.html', threads=statuses, tag=id, app=app, attribution=attribution, render_date=datetime.now())
|
||||
|
||||
|
||||
@threads.route('/<path:id>')
|
||||
@cache.cached(timeout=300)
|
||||
def thread(id):
|
||||
attribution = get_attribution()
|
||||
app = get_app_config()
|
||||
status = fetch_thread(id)
|
||||
status['summary'] = utils.clean_html(status['content']).strip()
|
||||
if len(status['summary']) > 69:
|
||||
status['summary'] = status['summary'][:69] + '...'
|
||||
return render_template('_home.html', threads=[status], app=app, attribution=attribution, render_date=datetime.now())
|
||||
|
||||
@threads.route('/api')
|
||||
@cache.cached(timeout=300)
|
||||
async def api():
|
||||
return await fetch_statuses();
|
||||
|
||||
@threads.route('/api/<path:id>')
|
||||
@cache.cached(timeout=300)
|
||||
def api_thread(id):
|
||||
return fetch_thread(id)
|
||||
|
||||
### statuses
|
||||
async def get(url, session):
|
||||
try:
|
||||
async with session.get(url, ssl=False) as response:
|
||||
|
@ -120,9 +106,6 @@ async def get(url, session):
|
|||
def get_status_url(ser, id):
|
||||
return f'{ser}/api/v1/statuses/{id}'
|
||||
|
||||
def server():
|
||||
return current_app.config['APPS']['threads']['server']
|
||||
|
||||
async def fetch_statuses():
|
||||
statuses = []
|
||||
urls = [get_status_url(server(), id) for id in thread_ids]
|
||||
|
@ -149,3 +132,50 @@ def get_descendants(server, status):
|
|||
if reply['account']['id'] == author_id and reply['in_reply_to_account_id'] == author_id:
|
||||
descendants.append(utils.clean_status(reply))
|
||||
return descendants
|
||||
|
||||
### routes
|
||||
@threads.route('/')
|
||||
@cache.cached(timeout=300)
|
||||
async def home():
|
||||
statuses = await fetch_statuses()
|
||||
attribution = get_attribution()
|
||||
app = get_app_config()
|
||||
tags = []
|
||||
|
||||
# List featured hashtags
|
||||
tags = get_featured_tags()
|
||||
|
||||
return render_template('_home.html', threads=statuses, tags=tags, app=app, attribution=attribution, render_date=datetime.now())
|
||||
|
||||
|
||||
@threads.route('/tag/<path:id>')
|
||||
@cache.cached(timeout=300)
|
||||
async def tag(id):
|
||||
attribution = get_attribution()
|
||||
app = get_app_config()
|
||||
statuses = get_account_tagged_statuses(id)
|
||||
|
||||
return render_template('_tag.html', threads=statuses, tag=id, app=app, attribution=attribution, render_date=datetime.now())
|
||||
|
||||
|
||||
@threads.route('/<path:id>')
|
||||
@cache.cached(timeout=300)
|
||||
def thread(id):
|
||||
attribution = get_attribution()
|
||||
app = get_app_config()
|
||||
status = fetch_thread(id)
|
||||
status['summary'] = utils.clean_html(status['content']).strip()
|
||||
if len(status['summary']) > 69:
|
||||
status['summary'] = status['summary'][:69] + '...'
|
||||
return render_template('_home.html', threads=[status], app=app, attribution=attribution, render_date=datetime.now())
|
||||
|
||||
@threads.route('/api')
|
||||
@cache.cached(timeout=300)
|
||||
async def api():
|
||||
return await fetch_statuses();
|
||||
|
||||
@threads.route('/api/<path:id>')
|
||||
@cache.cached(timeout=300)
|
||||
def api_thread(id):
|
||||
return fetch_thread(id)
|
||||
|
||||
|
|
Loading…
Reference in a new issue