Files
SocialPub/tools/pasture/town/dialects/mastodon.py
T

57 lines
2.7 KiB
Python
Raw Normal View History

"""Mastodon 4.7: accounts and tokens made in one `rails runner` (it has no password grant, and tootctl boots Rails once
per account), objects read from its Postgres database (`mastodon`)."""
import json
from core import podman
from dialects.base import Stored
from dialects.mastodon_api import MastodonApi
VIS = {0: "public", 1: "unlisted", 2: "followers", 3: "direct", 4: "limited"}
PROVISION = r'''
app = Doorkeeper::Application.find_or_create_by!(name: "pasture-town") { |a| a.redirect_uri = "urn:ietf:wg:oauth:2.0:oob"; a.scopes = "read write follow" }
out = {}
JSON.parse(STDIN.read).each do |u|
account = Account.find_local(u["username"])
if account.nil?
account = Account.new(username: u["username"])
user = User.new(email: "#{u["username"]}@mastodon.test", password: u["password"], agreement: true, approved: true,
confirmed_at: Time.now.utc, account: account)
user.save!
account.reload
end
account.user.approve! unless account.user.approved?
account.user.confirm unless account.user.confirmed?
token = Doorkeeper::AccessToken.find_or_create_for(application: app, resource_owner: account.user, scopes: Doorkeeper::OAuth::Scopes.from_string("read write follow"), expires_in: nil, use_refresh_token: false)
out[u["username"]] = token.token
end
puts "TOWN" + out.to_json
'''
class Mastodon(MastodonApi):
platform = "mastodon"
caps = MastodonApi.caps | {"quote"}
def provision(self, accounts):
payload = json.dumps([{"username": a.username, "password": a.password} for a in accounts])
out = podman.exec_("pasture-mastodon", "bin/rails", "runner", PROVISION, input=payload, timeout=600)
tokens = json.loads(next(line[4:] for line in out.splitlines() if line.startswith("TOWN")))
return [self.session_from_token(a, tokens[a.username]) for a in accounts]
def _rows(self, uris):
if not uris:
return {}
rows = podman.psql("mastodon", """
select s.id::text as local_id, s.uri, s.deleted_at is not null as deleted, s.visibility, s.text,
s.spoiler_text as cw, s.edited_at is not null as edited, p.uri as parent_uri,
coalesce(st.favourites_count, 0) as likes, coalesce(st.reblogs_count, 0) as boosts,
coalesce(st.replies_count, 0) as replies, pl.cached_tallies as votes
from statuses s
left join statuses p on p.id = s.in_reply_to_id
left join status_stats st on st.status_id = s.id
left join polls pl on pl.status_id = s.id
where s.reblog_of_id is null and s.uri = any(string_to_array(:'p1', ' '))""", " ".join(uris))
return {r["uri"]: Stored(True, r["deleted"], r["local_id"], VIS.get(r["visibility"]), r["text"], r["cw"] or None,
r["edited"], r["parent_uri"], r["likes"], r["boosts"], r["replies"], r["votes"], None, r)
for r in rows}