Status are sent to mastodon

This commit is contained in:
Chocobozzz 2017-12-19 10:34:56 +01:00
parent ce33ee01cd
commit e12a009254
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
20 changed files with 133 additions and 111 deletions

View File

@ -1,8 +1,8 @@
import * as validator from 'validator'
import { CONSTRAINTS_FIELDS } from '../../../initializers'
import { isAccountNameValid } from '../accounts'
import { exists, isUUIDValid } from '../misc'
import { isVideoChannelDescriptionValid, isVideoChannelNameValid } from '../video-channels'
import { exists } from '../misc'
import { isVideoChannelNameValid } from '../video-channels'
import { isActivityPubUrlValid, isBaseActivityValid, setValidAttributedTo } from './misc'
function isActorEndpointsObjectValid (endpointObject: any) {
@ -23,41 +23,39 @@ function isActorPublicKeyValid (publicKey: string) {
return exists(publicKey) &&
typeof publicKey === 'string' &&
publicKey.startsWith('-----BEGIN PUBLIC KEY-----') &&
publicKey.endsWith('-----END PUBLIC KEY-----') &&
publicKey.indexOf('-----END PUBLIC KEY-----') !== -1 &&
validator.isLength(publicKey, CONSTRAINTS_FIELDS.ACTOR.PUBLIC_KEY)
}
const actorNameRegExp = new RegExp('[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_]+')
function isActorPreferredUsernameValid (preferredUsername: string) {
return isAccountNameValid(preferredUsername) || isVideoChannelNameValid(preferredUsername)
return exists(preferredUsername) && validator.matches(preferredUsername, actorNameRegExp)
}
const actorNameRegExp = new RegExp('[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_]+')
function isActorNameValid (name: string) {
return exists(name) && validator.matches(name, actorNameRegExp)
return isAccountNameValid(name) || isVideoChannelNameValid(name)
}
function isActorPrivateKeyValid (privateKey: string) {
return exists(privateKey) &&
typeof privateKey === 'string' &&
privateKey.startsWith('-----BEGIN RSA PRIVATE KEY-----') &&
privateKey.endsWith('-----END RSA PRIVATE KEY-----') &&
// Sometimes there is a \n at the end, so just assert the string contains the end mark
privateKey.indexOf('-----END RSA PRIVATE KEY-----') !== -1 &&
validator.isLength(privateKey, CONSTRAINTS_FIELDS.ACTOR.PRIVATE_KEY)
}
function isRemoteActorValid (remoteActor: any) {
return isActivityPubUrlValid(remoteActor.id) &&
isUUIDValid(remoteActor.uuid) &&
isActorTypeValid(remoteActor.type) &&
isActivityPubUrlValid(remoteActor.following) &&
isActivityPubUrlValid(remoteActor.followers) &&
isActivityPubUrlValid(remoteActor.inbox) &&
isActivityPubUrlValid(remoteActor.outbox) &&
isActorNameValid(remoteActor.name) &&
isActorPreferredUsernameValid(remoteActor.preferredUsername) &&
isActivityPubUrlValid(remoteActor.url) &&
isActorPublicKeyObjectValid(remoteActor.publicKey) &&
isActorEndpointsObjectValid(remoteActor.endpoints) &&
(!remoteActor.summary || isVideoChannelDescriptionValid(remoteActor.summary)) &&
setValidAttributedTo(remoteActor) &&
// If this is not an account, it should be attributed to an account
// In PeerTube we use this to attach a video channel to a specific account

View File

@ -316,7 +316,7 @@ const CACHE = {
}
}
const ACCEPT_HEADERS = ACTIVITY_PUB.POTENTIAL_ACCEPT_HEADERS.concat('html', 'application/json')
const ACCEPT_HEADERS = [ 'html', 'application/json' ].concat(ACTIVITY_PUB.POTENTIAL_ACCEPT_HEADERS)
// ---------------------------------------------------------------------------

View File

@ -22,7 +22,7 @@ async function up (utils: {
id integer NOT NULL,
type enum_actor_type NOT NULL,
uuid uuid NOT NULL,
name character varying(255) NOT NULL,
"preferredUsername" character varying(255) NOT NULL,
url character varying(2000) NOT NULL,
"publicKey" character varying(5000),
"privateKey" character varying(5000),
@ -50,7 +50,7 @@ async function up (utils: {
`ALTER SEQUENCE actor_id_seq OWNED BY actor.id`,
`ALTER TABLE ONLY actor ALTER COLUMN id SET DEFAULT nextval('actor_id_seq'::regclass)`,
`ALTER TABLE ONLY actor ADD CONSTRAINT actor_pkey PRIMARY KEY (id);`,
`CREATE UNIQUE INDEX actor_name_server_id ON actor USING btree (name, "serverId")`,
`CREATE UNIQUE INDEX actor_preferred_username_server_id ON actor USING btree ("preferredUsername", "serverId")`,
`ALTER TABLE ONLY actor
ADD CONSTRAINT "actor_avatarId_fkey" FOREIGN KEY ("avatarId") REFERENCES avatar(id) ON UPDATE CASCADE ON DELETE CASCADE`,
`ALTER TABLE ONLY actor
@ -68,7 +68,7 @@ async function up (utils: {
`
INSERT INTO "actor"
(
type, uuid, name, url, "publicKey", "privateKey", "followersCount", "followingCount", "inboxUrl", "outboxUrl",
type, uuid, "preferredUsername", url, "publicKey", "privateKey", "followersCount", "followingCount", "inboxUrl", "outboxUrl",
"sharedInboxUrl", "followersUrl", "followingUrl", "avatarId", "serverId", "createdAt", "updatedAt"
)
SELECT
@ -83,7 +83,7 @@ async function up (utils: {
`
INSERT INTO "actor"
(
type, uuid, name, url, "publicKey", "privateKey", "followersCount", "followingCount", "inboxUrl", "outboxUrl",
type, uuid, "preferredUsername", url, "publicKey", "privateKey", "followersCount", "followingCount", "inboxUrl", "outboxUrl",
"sharedInboxUrl", "followersUrl", "followingUrl", "avatarId", "serverId", "createdAt", "updatedAt"
)
SELECT
@ -119,7 +119,7 @@ async function up (utils: {
const query = `
INSERT INTO actor
(
type, uuid, name, url, "publicKey", "privateKey", "followersCount", "followingCount", "inboxUrl", "outboxUrl",
type, uuid, "preferredUsername", url, "publicKey", "privateKey", "followersCount", "followingCount", "inboxUrl", "outboxUrl",
"sharedInboxUrl", "followersUrl", "followingUrl", "avatarId", "serverId", "createdAt", "updatedAt"
)
SELECT

View File

@ -11,7 +11,7 @@ import { ActorModel } from '../../models/activitypub/actor'
import { ServerModel } from '../../models/server/server'
import { VideoChannelModel } from '../../models/video/video-channel'
// Set account keys, this could be long so process after the account creation and do not block the client
// Set account keys, this could be long so process after the account creation and do not block the client
function setAsyncActorKeys (actor: ActorModel) {
return createPrivateAndPublicKeys()
.then(({ publicKey, privateKey }) => {
@ -107,7 +107,7 @@ function saveActorAndServerAndModelIfNotExist (
type FetchRemoteActorResult = {
actor: ActorModel
preferredUsername: string
name: string
summary: string
attributedTo: ActivityPubAttributedTo[]
}
@ -142,8 +142,8 @@ async function fetchRemoteActor (actorUrl: string): Promise<FetchRemoteActorResu
const actor = new ActorModel({
type: actorJSON.type,
uuid: actorJSON.uuid,
name: actorJSON.name,
url: actorJSON.url,
preferredUsername: actorJSON.preferredUsername,
url: actorJSON.id,
publicKey: actorJSON.publicKey.publicKeyPem,
privateKey: null,
followersCount: followersCount,
@ -155,19 +155,20 @@ async function fetchRemoteActor (actorUrl: string): Promise<FetchRemoteActorResu
followingUrl: actorJSON.following
})
const name = actorJSON.name || actorJSON.preferredUsername
return {
actor,
preferredUsername: actorJSON.preferredUsername,
name,
summary: actorJSON.summary,
attributedTo: actorJSON.attributedTo
}
}
function buildActorInstance (type: ActivityPubActorType, url: string, name: string, uuid?: string) {
function buildActorInstance (type: ActivityPubActorType, url: string, preferredUsername: string, uuid?: string) {
return new ActorModel({
type,
url,
name,
preferredUsername,
uuid,
publicKey: null,
privateKey: null,
@ -210,7 +211,7 @@ async function fetchActorTotalItems (url: string) {
function saveAccount (actor: ActorModel, result: FetchRemoteActorResult, t: Transaction) {
const account = new AccountModel({
name: result.preferredUsername,
name: result.name,
actorId: actor.id
})
@ -219,7 +220,7 @@ function saveAccount (actor: ActorModel, result: FetchRemoteActorResult, t: Tran
async function saveVideoChannel (actor: ActorModel, result: FetchRemoteActorResult, ownerActor: ActorModel, t: Transaction) {
const videoChannel = new VideoChannelModel({
name: result.preferredUsername,
name: result.name,
description: result.summary,
actorId: actor.id,
accountId: ownerActor.Account.id

View File

@ -1,5 +1,5 @@
import { Transaction } from 'sequelize'
import { Activity } from '../../../../shared/models/activitypub'
import { Activity, ActivityAudience } from '../../../../shared/models/activitypub'
import { logger } from '../../../helpers'
import { ACTIVITY_PUB } from '../../../initializers'
import { ActorModel } from '../../../models/activitypub/actor'
@ -116,6 +116,10 @@ async function getAudience (actorSender: ActorModel, t: Transaction, isPublic =
return { to, cc }
}
function audiencify (object: any, audience: ActivityAudience) {
return Object.assign(object, audience)
}
async function computeFollowerUris (toActorFollower: ActorModel[], followersException: ActorModel[], t: Transaction) {
const toActorFollowerIds = toActorFollower.map(a => a.id)
@ -133,5 +137,6 @@ export {
getOriginVideoAudience,
getActorsInvolvedInVideo,
getObjectFollowersAudience,
forwardActivity
forwardActivity,
audiencify
}

View File

@ -1,16 +1,20 @@
import { Transaction } from 'sequelize'
import { ActivityAccept } from '../../../../shared/models/activitypub'
import { ActivityAccept, ActivityFollow } from '../../../../shared/models/activitypub'
import { ActorModel } from '../../../models/activitypub/actor'
import { ActorFollowModel } from '../../../models/activitypub/actor-follow'
import { getActorFollowAcceptActivityPubUrl } from '../url'
import { getActorFollowAcceptActivityPubUrl, getActorFollowActivityPubUrl } from '../url'
import { unicastTo } from './misc'
import { followActivityData } from './send-follow'
async function sendAccept (actorFollow: ActorFollowModel, t: Transaction) {
const follower = actorFollow.ActorFollower
const me = actorFollow.ActorFollowing
const followUrl = getActorFollowActivityPubUrl(actorFollow)
const followData = followActivityData(followUrl, follower, me)
const url = getActorFollowAcceptActivityPubUrl(actorFollow)
const data = acceptActivityData(url, me)
const data = acceptActivityData(url, me, followData)
return unicastTo(data, me, follower.inboxUrl, t)
}
@ -23,10 +27,11 @@ export {
// ---------------------------------------------------------------------------
function acceptActivityData (url: string, byActor: ActorModel): ActivityAccept {
function acceptActivityData (url: string, byActor: ActorModel, followActivityData: ActivityFollow): ActivityAccept {
return {
type: 'Accept',
id: url,
actor: byActor.url
actor: byActor.url,
object: followActivityData
}
}

View File

@ -7,6 +7,7 @@ import { VideoModel } from '../../../models/video/video'
import { VideoAbuseModel } from '../../../models/video/video-abuse'
import { getVideoAbuseActivityPubUrl, getVideoDislikeActivityPubUrl, getVideoViewActivityPubUrl } from '../url'
import {
audiencify,
broadcastToFollowers,
getActorsInvolvedInVideo,
getAudience,
@ -16,9 +17,11 @@ import {
} from './misc'
async function sendCreateVideo (video: VideoModel, t: Transaction) {
const byActor = video.VideoChannel.Account.Actor
if (video.privacy === VideoPrivacy.PRIVATE) return
const byActor = video.VideoChannel.Account.Actor
const videoObject = video.toActivityPubObject()
const audience = await getAudience(byActor, t, video.privacy === VideoPrivacy.PUBLIC)
const data = await createActivityData(video.url, byActor, videoObject, t, audience)
@ -93,14 +96,12 @@ async function createActivityData (
audience = await getAudience(byActor, t)
}
return {
return audiencify({
type: 'Create',
id: url,
actor: byActor.url,
to: audience.to,
cc: audience.cc,
object
}
object: audiencify(object, audience)
}, audience)
}
function createDislikeActivityData (byActor: ActorModel, video: VideoModel) {

View File

@ -4,6 +4,7 @@ import { ActorModel } from '../../../models/activitypub/actor'
import { VideoModel } from '../../../models/video/video'
import { getVideoLikeActivityPubUrl } from '../url'
import {
audiencify,
broadcastToFollowers,
getActorsInvolvedInVideo,
getAudience,
@ -44,14 +45,12 @@ async function likeActivityData (
audience = await getAudience(byActor, t)
}
return {
return audiencify({
type: 'Like',
id: url,
actor: byActor.url,
to: audience.to,
cc: audience.cc,
object: video.url
}
}, audience)
}
// ---------------------------------------------------------------------------

View File

@ -11,6 +11,7 @@ import { ActorFollowModel } from '../../../models/activitypub/actor-follow'
import { VideoModel } from '../../../models/video/video'
import { getActorFollowActivityPubUrl, getUndoActivityPubUrl, getVideoDislikeActivityPubUrl, getVideoLikeActivityPubUrl } from '../url'
import {
audiencify,
broadcastToFollowers,
getActorsInvolvedInVideo,
getAudience,
@ -112,12 +113,10 @@ async function undoActivityData (
audience = await getAudience(byActor, t)
}
return {
return audiencify({
type: 'Undo',
id: url,
actor: byActor.url,
to: audience.to,
cc: audience.cc,
object
}
}, audience)
}

View File

@ -5,7 +5,7 @@ import { ActorModel } from '../../../models/activitypub/actor'
import { VideoModel } from '../../../models/video/video'
import { VideoShareModel } from '../../../models/video/video-share'
import { getUpdateActivityPubUrl } from '../url'
import { broadcastToFollowers, getAudience } from './misc'
import { audiencify, broadcastToFollowers, getAudience } from './misc'
async function sendUpdateVideo (video: VideoModel, t: Transaction) {
const byActor = video.VideoChannel.Account.Actor
@ -41,12 +41,10 @@ async function updateActivityData (
audience = await getAudience(byActor, t)
}
return {
return audiencify({
type: 'Update',
id: url,
actor: byActor.url,
to: audience.to,
cc: audience.cc,
object
}
object: audiencify(object, audience)
}, audience)
}

View File

@ -1,10 +1,13 @@
import { Transaction } from 'sequelize'
import { VideoPrivacy } from '../../../shared/models/videos'
import { getServerActor } from '../../helpers'
import { VideoModel } from '../../models/video/video'
import { VideoShareModel } from '../../models/video/video-share'
import { sendVideoAnnounceToFollowers } from './send'
async function shareVideoByServerAndChannel (video: VideoModel, t: Transaction) {
if (video.privacy === VideoPrivacy.PRIVATE) return
const serverActor = await getServerActor()
const serverShare = VideoShareModel.create({

View File

@ -1,15 +1,17 @@
import { doRequest, logger } from '../../../helpers'
import { ActivityPubHttpPayload, computeBody, maybeRetryRequestLater } from './activitypub-http-job-scheduler'
import { ActivityPubHttpPayload, buildSignedRequestOptions, computeBody, maybeRetryRequestLater } from './activitypub-http-job-scheduler'
async function process (payload: ActivityPubHttpPayload, jobId: number) {
logger.info('Processing ActivityPub broadcast in job %d.', jobId)
const body = await computeBody(payload)
const httpSignatureOptions = await buildSignedRequestOptions(payload)
const options = {
method: 'POST',
uri: '',
json: body
json: body,
httpSignature: httpSignatureOptions
}
for (const uri of payload.uris) {

View File

@ -1,5 +1,5 @@
import { JobCategory } from '../../../../shared'
import { buildSignedActivity, logger } from '../../../helpers'
import { buildSignedActivity, getServerActor, logger } from '../../../helpers'
import { ACTIVITY_PUB } from '../../../initializers'
import { ActorModel } from '../../../models/activitypub/actor'
import { JobHandler, JobScheduler } from '../job-scheduler'
@ -46,16 +46,36 @@ async function computeBody (payload: ActivityPubHttpPayload) {
if (payload.signatureActorId) {
const actorSignature = await ActorModel.load(payload.signatureActorId)
if (!actorSignature) throw new Error('Unknown signature account id.')
if (!actorSignature) throw new Error('Unknown signature actor id.')
body = await buildSignedActivity(actorSignature, payload.body)
}
return body
}
async function buildSignedRequestOptions (payload: ActivityPubHttpPayload) {
let actor: ActorModel
if (payload.signatureActorId) {
actor = await ActorModel.load(payload.signatureActorId)
if (!actor) throw new Error('Unknown signature actor id.')
} else {
// We need to sign the request, so use the server
actor = await getServerActor()
}
const keyId = actor.getWebfingerUrl()
return {
algorithm: 'rsa-sha256',
authorizationHeaderName: 'Signature',
keyId,
key: actor.privateKey
}
}
export {
ActivityPubHttpPayload,
activitypubHttpJobScheduler,
maybeRetryRequestLater,
computeBody
computeBody,
buildSignedRequestOptions
}

View File

@ -1,16 +1,18 @@
import { doRequest, logger } from '../../../helpers'
import { ActivityPubHttpPayload, computeBody, maybeRetryRequestLater } from './activitypub-http-job-scheduler'
import { ActivityPubHttpPayload, buildSignedRequestOptions, computeBody, maybeRetryRequestLater } from './activitypub-http-job-scheduler'
async function process (payload: ActivityPubHttpPayload, jobId: number) {
logger.info('Processing ActivityPub unicast in job %d.', jobId)
const body = await computeBody(payload)
const httpSignatureOptions = await buildSignedRequestOptions(payload)
const uri = payload.uris[0]
const options = {
method: 'POST',
uri,
json: body
json: body,
httpSignature: httpSignatureOptions
}
try {

View File

@ -1,4 +1,5 @@
import * as Bluebird from 'bluebird'
import { VideoPrivacy } from '../../../../shared/models/videos'
import { computeResolutionsToTranscode, logger } from '../../../helpers'
import { sequelizeTypescript } from '../../../initializers'
import { VideoModel } from '../../../models/video/video'
@ -35,9 +36,11 @@ async function onSuccess (jobId: number, video: VideoModel, jobScheduler: JobSch
// Video does not exist anymore
if (!videoDatabase) return undefined
// Now we'll add the video's meta data to our followers
await sendCreateVideo(video, undefined)
await shareVideoByServerAndChannel(video, undefined)
if (video.privacy !== VideoPrivacy.PRIVATE) {
// Now we'll add the video's meta data to our followers
await sendCreateVideo(video, undefined)
await shareVideoByServerAndChannel(video, undefined)
}
const originalFileHeight = await videoDatabase.getOriginalFileHeight()

View File

@ -1,4 +1,5 @@
import { VideoResolution } from '../../../../shared'
import { VideoPrivacy } from '../../../../shared/models/videos'
import { logger } from '../../../helpers'
import { VideoModel } from '../../../models/video/video'
import { sendUpdateVideo } from '../../activitypub/send'
@ -31,7 +32,9 @@ async function onSuccess (jobId: number, video: VideoModel) {
// Video does not exist anymore
if (!videoDatabase) return undefined
await sendUpdateVideo(video, undefined)
if (video.privacy !== VideoPrivacy.PRIVATE) {
await sendUpdateVideo(video, undefined)
}
return undefined
}

View File

@ -9,11 +9,13 @@ import { ActorModel } from '../models/activitypub/actor'
async function checkSignature (req: Request, res: Response, next: NextFunction) {
const signatureObject: ActivityPubSignature = req.body.signature
logger.debug('Checking signature of actor %s...', signatureObject.creator)
const [ creator ] = signatureObject.creator.split('#')
logger.debug('Checking signature of actor %s...', creator)
let actor: ActorModel
try {
actor = await getOrCreateActorAndServerAndModel(signatureObject.creator)
actor = await getOrCreateActorAndServerAndModel(creator)
} catch (err) {
logger.error('Cannot create remote actor and check signature.', err)
return res.sendStatus(403)
@ -32,6 +34,7 @@ async function checkSignature (req: Request, res: Response, next: NextFunction)
function executeIfActivityPub (fun: RequestHandler | RequestHandler[]) {
return (req: Request, res: Response, next: NextFunction) => {
const accepted = req.accepts(ACCEPT_HEADERS)
console.log(accepted)
if (accepted === false || ACTIVITY_PUB.POTENTIAL_ACCEPT_HEADERS.indexOf(accepted) === -1) {
return next()
}

View File

@ -2,32 +2,15 @@ import { values } from 'lodash'
import { join } from 'path'
import * as Sequelize from 'sequelize'
import {
AllowNull,
BelongsTo,
Column,
CreatedAt,
DataType,
Default, DefaultScope,
ForeignKey,
HasMany,
HasOne,
Is,
IsUUID,
Model,
Scopes,
Table,
UpdatedAt
AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, DefaultScope, ForeignKey, HasMany, HasOne, Is, IsUUID, Model, Scopes,
Table, UpdatedAt
} from 'sequelize-typescript'
import { ActivityPubActorType } from '../../../shared/models/activitypub'
import { Avatar } from '../../../shared/models/avatars/avatar.model'
import { activityPubContextify } from '../../helpers'
import {
isActivityPubUrlValid,
isActorFollowersCountValid,
isActorFollowingCountValid,
isActorNameValid,
isActorPrivateKeyValid,
isActorPublicKeyValid
isActivityPubUrlValid, isActorFollowersCountValid, isActorFollowingCountValid, isActorPreferredUsernameValid,
isActorPrivateKeyValid, isActorPublicKeyValid
} from '../../helpers/custom-validators/activitypub'
import { ACTIVITY_PUB_ACTOR_TYPES, AVATARS_DIR, CONFIG, CONSTRAINTS_FIELDS } from '../../initializers'
import { AccountModel } from '../account/account'
@ -71,7 +54,7 @@ enum ScopeNames {
tableName: 'actor',
indexes: [
{
fields: [ 'name', 'serverId' ],
fields: [ 'preferredUsername', 'serverId' ],
unique: true
}
]
@ -89,9 +72,9 @@ export class ActorModel extends Model<ActorModel> {
uuid: string
@AllowNull(false)
@Is('ActorName', value => throwIfNotValid(value, isActorNameValid, 'actor name'))
@Is('ActorPreferredUsername', value => throwIfNotValid(value, isActorPreferredUsernameValid, 'actor preferred username'))
@Column
name: string
preferredUsername: string
@AllowNull(false)
@Is('ActorUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'url'))
@ -212,16 +195,6 @@ export class ActorModel extends Model<ActorModel> {
return ActorModel.scope(ScopeNames.FULL).findById(id)
}
static loadByUUID (uuid: string) {
const query = {
where: {
uuid
}
}
return ActorModel.scope(ScopeNames.FULL).findOne(query)
}
static listByFollowersUrls (followersUrls: string[], transaction?: Sequelize.Transaction) {
const query = {
where: {
@ -235,10 +208,10 @@ export class ActorModel extends Model<ActorModel> {
return ActorModel.scope(ScopeNames.FULL).findAll(query)
}
static loadLocalByName (name: string) {
static loadLocalByName (preferredUsername: string) {
const query = {
where: {
name,
preferredUsername,
serverId: null
}
}
@ -246,10 +219,10 @@ export class ActorModel extends Model<ActorModel> {
return ActorModel.scope(ScopeNames.FULL).findOne(query)
}
static loadByNameAndHost (name: string, host: string) {
static loadByNameAndHost (preferredUsername: string, host: string) {
const query = {
where: {
name
preferredUsername
},
include: [
{
@ -286,17 +259,15 @@ export class ActorModel extends Model<ActorModel> {
}
}
let host = CONFIG.WEBSERVER.HOST
let score: number
if (this.Server) {
host = this.Server.host
score = this.Server.score
}
return {
id: this.id,
uuid: this.uuid,
host,
host: this.getHost(),
score,
followingCount: this.followingCount,
followersCount: this.followersCount,
@ -304,7 +275,7 @@ export class ActorModel extends Model<ActorModel> {
}
}
toActivityPubObject (preferredUsername: string, type: 'Account' | 'Application' | 'VideoChannel') {
toActivityPubObject (name: string, type: 'Account' | 'Application' | 'VideoChannel') {
let activityPubType
if (type === 'Account') {
activityPubType = 'Person' as 'Person'
@ -321,9 +292,9 @@ export class ActorModel extends Model<ActorModel> {
followers: this.getFollowersUrl(),
inbox: this.inboxUrl,
outbox: this.outboxUrl,
preferredUsername,
preferredUsername: this.preferredUsername,
url: this.url,
name: this.name,
name,
endpoints: {
sharedInbox: this.sharedInboxUrl
},
@ -373,4 +344,12 @@ export class ActorModel extends Model<ActorModel> {
isOwned () {
return this.serverId === null
}
getWebfingerUrl () {
return 'acct:' + this.preferredUsername + '@' + this.getHost()
}
getHost () {
return this.Server ? this.Server.host : CONFIG.WEBSERVER.HOST
}
}

View File

@ -46,6 +46,7 @@ export interface ActivityFollow extends BaseActivity {
export interface ActivityAccept extends BaseActivity {
type: 'Accept'
object: ActivityFollow
}
export interface ActivityAnnounce extends BaseActivity {

View File

@ -2378,9 +2378,9 @@ jsonify@~0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
"jsonld-signatures@https://github.com/digitalbazaar/jsonld-signatures#rsa2017":
"jsonld-signatures@https://github.com/Chocobozzz/jsonld-signatures#rsa2017":
version "1.2.2-2"
resolved "https://github.com/digitalbazaar/jsonld-signatures#ccb5ca156d72d7632131080d6ef564681791391e"
resolved "https://github.com/Chocobozzz/jsonld-signatures#77660963e722eb4541d2d255f9d9d4216329665f"
dependencies:
bitcore-message "github:CoMakery/bitcore-message#dist"
jsonld "^0.5.12"