kopia lustrzana https://github.com/snarfed/bridgy-fed
Porównaj commity
12 Commity
4d5d5afb5d
...
4f463743fa
Autor | SHA1 | Data |
---|---|---|
dependabot[bot] | 4f463743fa | |
dependabot[bot] | 31cc598d15 | |
Ryan Barrett | f1531b44e7 | |
Ryan Barrett | 10e5b00dd6 | |
dependabot[bot] | fe41336110 | |
dependabot[bot] | 057fb73e45 | |
Ryan Barrett | 5c470a4647 | |
Ryan Barrett | 55b8063aa8 | |
Ryan Barrett | 4ed45e5af5 | |
dependabot[bot] | 798db9b606 | |
dependabot[bot] | e86b95a117 | |
Ryan Barrett | df321234c0 |
|
@ -8,7 +8,7 @@ from urllib.parse import quote_plus, urljoin, urlparse
|
|||
|
||||
from flask import abort, g, redirect, request
|
||||
from google.cloud import ndb
|
||||
from google.cloud.ndb.query import OR
|
||||
from google.cloud.ndb.query import FilterNode, OR, Query
|
||||
from granary import as1, as2
|
||||
from httpsig import HeaderVerifier
|
||||
from httpsig.requests_auth import HTTPSignatureAuth
|
||||
|
@ -51,6 +51,10 @@ SECURITY_CONTEXT = 'https://w3id.org/security/v1'
|
|||
# https://seb.jambor.dev/posts/understanding-activitypub-part-4-threads/#the-instance-actor
|
||||
_INSTANCE_ACTOR = None
|
||||
|
||||
# populated in User.status
|
||||
WEB_OPT_OUT_DOMAINS = None
|
||||
|
||||
|
||||
def instance_actor():
|
||||
global _INSTANCE_ACTOR
|
||||
if _INSTANCE_ACTOR is None:
|
||||
|
@ -87,7 +91,7 @@ class ActivityPub(User, Protocol):
|
|||
def web_url(self):
|
||||
"""Returns this user's web URL aka web_url, eg ``https://foo.com/``."""
|
||||
if self.obj and self.obj.as1:
|
||||
url = util.get_url(self.obj.as1)
|
||||
url = as1.get_url(self.obj.as1)
|
||||
if url:
|
||||
return url
|
||||
|
||||
|
@ -103,6 +107,27 @@ class ActivityPub(User, Protocol):
|
|||
|
||||
return as2.address(self.key.id())
|
||||
|
||||
@ndb.ComputedProperty
|
||||
def status(self):
|
||||
"""Override :meth:`Model.status` and include Web opted out domains."""
|
||||
global WEB_OPT_OUT_DOMAINS
|
||||
if WEB_OPT_OUT_DOMAINS is None:
|
||||
WEB_OPT_OUT_DOMAINS = {
|
||||
key.id() for key in Query(
|
||||
'MagicKey',
|
||||
filters=FilterNode('manual_opt_out', '=', True)
|
||||
).fetch(keys_only=True)
|
||||
}
|
||||
logger.info(f'Loaded {len(WEB_OPT_OUT_DOMAINS)} manually opted out Web users')
|
||||
|
||||
status = super().status
|
||||
if status:
|
||||
return status
|
||||
|
||||
return util.domain_or_parent_in(util.domain_from_link(self.key.id()),
|
||||
WEB_OPT_OUT_DOMAINS)
|
||||
|
||||
|
||||
@classmethod
|
||||
def owns_id(cls, id):
|
||||
"""Returns None if ``id`` is an http(s) URL, False otherwise.
|
||||
|
|
|
@ -21,6 +21,7 @@ from granary import as1, bluesky
|
|||
from lexrpc import Client
|
||||
import requests
|
||||
from requests import RequestException
|
||||
from oauth_dropins.webutil.appengine_config import ndb_client
|
||||
from oauth_dropins.webutil.appengine_info import DEBUG
|
||||
from oauth_dropins.webutil import util
|
||||
from oauth_dropins.webutil.util import json_dumps, json_loads
|
||||
|
@ -40,7 +41,7 @@ from protocol import Protocol
|
|||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
arroba.server.storage = DatastoreStorage()
|
||||
arroba.server.storage = DatastoreStorage(ndb_client=ndb_client)
|
||||
|
||||
LEXICONS = Client('https://unused').defs
|
||||
|
||||
|
|
7
hub.py
7
hub.py
|
@ -1,26 +1,19 @@
|
|||
"""Single-instance hub for ATProto and Nostr websocket subscriptions."""
|
||||
from datetime import datetime, timedelta
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
from pathlib import Path
|
||||
from threading import Timer
|
||||
|
||||
import arroba.server
|
||||
from arroba.datastore_storage import DatastoreStorage
|
||||
from arroba import xrpc_sync
|
||||
from flask import Flask, request
|
||||
import google.cloud.logging
|
||||
import lexrpc.client
|
||||
import lexrpc.server
|
||||
import lexrpc.flask_server
|
||||
from oauth_dropins.webutil import (
|
||||
appengine_info,
|
||||
appengine_config,
|
||||
flask_util,
|
||||
util,
|
||||
)
|
||||
import requests
|
||||
|
||||
# all protocols, and atproto-poll-notifs task handler
|
||||
import activitypub, atproto, web
|
||||
|
|
1
pages.py
1
pages.py
|
@ -35,6 +35,7 @@ with app.test_request_context('/'):
|
|||
logger = logging.getLogger(__name__)
|
||||
|
||||
TEMPLATE_VARS = {
|
||||
'as1': as1,
|
||||
'as2': as2,
|
||||
'g': g,
|
||||
'isinstance': isinstance,
|
||||
|
|
|
@ -42,7 +42,7 @@ google-cloud-audit-log==0.2.5
|
|||
google-cloud-core==2.3.2
|
||||
google-cloud-datastore==2.16.1
|
||||
google-cloud-dns==0.35.0
|
||||
google-cloud-error-reporting==1.10.0
|
||||
google-cloud-error-reporting==1.11.0
|
||||
google-cloud-logging==3.10.0
|
||||
google-cloud-ndb==2.3.1
|
||||
google-cloud-tasks==2.16.3
|
||||
|
@ -57,10 +57,11 @@ html5lib==1.1
|
|||
humanfriendly==10.0
|
||||
humanize==4.9.0
|
||||
idna==3.6
|
||||
iterators==0.2.0
|
||||
itsdangerous==2.1.2
|
||||
Jinja2==3.1.3
|
||||
jsonschema==4.21.1
|
||||
lxml==5.1.0
|
||||
lxml==5.2.0
|
||||
MarkupSafe==2.1.5
|
||||
mf2py==2.0.1
|
||||
mf2util==0.5.2
|
||||
|
@ -76,7 +77,7 @@ proto-plus==1.23.0
|
|||
protobuf==4.24.3
|
||||
pyasn1==0.6.0
|
||||
pyasn1-modules==0.4.0
|
||||
pycparser==2.21
|
||||
pycparser==2.22
|
||||
pycryptodome==3.20.0
|
||||
pyjwt==2.8.0
|
||||
pymemcache==4.0.0
|
||||
|
@ -106,6 +107,6 @@ webencodings==0.5.1
|
|||
WebOb==1.8.7
|
||||
websocket-client==1.7.0
|
||||
websockets==12.0
|
||||
Werkzeug==3.0.1
|
||||
Werkzeug==3.0.2
|
||||
wrapt==1.16.0
|
||||
wsproto==1.2.0
|
||||
|
|
|
@ -2175,6 +2175,10 @@ class ActivityPubUtilsTest(TestCase):
|
|||
ignore=['to', 'attachment'])
|
||||
|
||||
def test_convert_follow_as1_no_from_user(self):
|
||||
# prevent HTTP fetches to infer protocol
|
||||
self.store_object(id='https://mas.to/6d1a', source_protocol='activitypub')
|
||||
self.store_object(id='https://user.com/', source_protocol='web')
|
||||
|
||||
obj = Object(our_as1=as2.to_as1(FOLLOW))
|
||||
self.assert_equals(FOLLOW, common.unwrap(ActivityPub.convert(obj)),
|
||||
ignore=['to'])
|
||||
|
@ -2255,6 +2259,19 @@ class ActivityPubUtilsTest(TestCase):
|
|||
})
|
||||
self.assertEqual('me.mas.to.ap.brid.gy', user.handle_as('atproto'))
|
||||
|
||||
def test_web_url_composite_url_object(self):
|
||||
actor_as2 = {
|
||||
'type': 'Person',
|
||||
'url': 'https://techhub.social/@foo',
|
||||
'attachment': [{
|
||||
'type': 'PropertyValue',
|
||||
'name': 'Twitter',
|
||||
'value': '<span class="h-card"><a href="https://techhub.social/@foo" class="u-url mention">@<span>foo</span></a></span>',
|
||||
}],
|
||||
}
|
||||
user = self.make_user('http://foo/actor', cls=ActivityPub, obj_as2=actor_as2)
|
||||
self.assertEqual('https://techhub.social/@foo', user.web_url())
|
||||
|
||||
def test_web_url(self):
|
||||
user = self.make_user('http://foo/actor', cls=ActivityPub)
|
||||
self.assertEqual('http://foo/actor', user.web_url())
|
||||
|
|
Ładowanie…
Reference in New Issue