57 lines
2.7 KiB
Python
57 lines
2.7 KiB
Python
"""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}
|