922 lines
31 KiB
JavaScript
922 lines
31 KiB
JavaScript
// Implementation of Activity Vocabulary, with extension for ActivityPub
|
|
// https://www.w3.org/TR/activitystreams-vocabulary
|
|
// https://www.w3.org/TR/activitypub
|
|
|
|
// Note: their prototypes are defined after to allow the definition of ObjectFetcher
|
|
// Base for other elements - to put things in common
|
|
const ASBase = function() {}
|
|
// Core types
|
|
const ASObject = function() {}
|
|
const ASLink = function() {}
|
|
const ASActivity = function() {}
|
|
const ASIntransitiveActivity = function() {}
|
|
const ASCollection = function() {}
|
|
const ASOrderedCollection = function() {}
|
|
const ASCollectionPage = function() {}
|
|
const ASOrderedCollectionPage = function() {}
|
|
// Extension for modelisation of ActivityPub actors
|
|
const ASActor = function() {}
|
|
|
|
// Extended Types
|
|
// Activity Types
|
|
const ASAccept = function() {}
|
|
const ASAdd = function() {}
|
|
const ASAnnounce = function() {}
|
|
const ASArrive = function() {}
|
|
const ASBlock = function() {}
|
|
const ASCreate = function() {}
|
|
const ASDelete = function() {}
|
|
const ASDislike = function() {}
|
|
const ASFlag = function() {}
|
|
const ASFollow = function() {}
|
|
const ASIgnore = function() {}
|
|
const ASInvite = function() {}
|
|
const ASJoin = function() {}
|
|
const ASLeave = function() {}
|
|
const ASLike = function() {}
|
|
const ASListen = function() {}
|
|
const ASMove = function() {}
|
|
const ASOffer = function() {}
|
|
const ASQuestion = function() {}
|
|
const ASReject = function() {}
|
|
const ASRead = function() {}
|
|
const ASRemove = function() {}
|
|
const ASTentativeReject = function() {}
|
|
const ASTentativeAccept = function() {}
|
|
const ASTravel = function() {}
|
|
const ASUndo = function() {}
|
|
const ASUpdate = function() {}
|
|
const ASView = function() {}
|
|
|
|
// Actor Types
|
|
const ASApplication = function() {}
|
|
const ASGroup = function() {}
|
|
const ASOrganization = function() {}
|
|
const ASPerson = function() {}
|
|
const ASService = function() {}
|
|
|
|
// Object Types
|
|
const ASArticle = function() {}
|
|
const ASAudio = function() {}
|
|
const ASDocument = function() {}
|
|
const ASEvent = function() {}
|
|
const ASImage = function() {}
|
|
const ASNote = function() {}
|
|
const ASPage = function() {}
|
|
const ASPlace = function() {}
|
|
const ASProfile = function() {}
|
|
const ASRelationship = function() {}
|
|
const ASTombstone = function() {}
|
|
const ASVideo = function() {}
|
|
|
|
// Link Types
|
|
const ASMention = function() {}
|
|
|
|
// Object fetcher
|
|
// Convert resources from the resource fetcher into Activity objects
|
|
import {TokenCollection} from './token-collection.js'
|
|
const Fetcher = {
|
|
// Cache of already accessed objects
|
|
knownObjects: {},
|
|
// Get an object
|
|
// Callback signature is function(load_ok, fetched_object, failure_message)
|
|
get: function(id, callback) {
|
|
if (Fetcher.knownObjects[id]) {
|
|
callback(true, Fetcher.knownObjects[id], '')
|
|
} else {
|
|
Fetcher.refresh(id, callback)
|
|
}
|
|
},
|
|
// Refresh a resource
|
|
// Callback signature is function(load_ok, fetched_object, failure_message)
|
|
refresh: function(id, callback) {
|
|
const request = new XMLHttpRequest()
|
|
request.onreadystatechange = function() {
|
|
if (request.readyState == 4 && request.status == 200) {
|
|
const answer = JSON.parse(request.responseText)
|
|
if (answer) {
|
|
// Build the object
|
|
const obj = Fetcher.fromJson(answer)
|
|
Fetcher.knownObjects[id] = obj
|
|
callback(true, obj, undefined)
|
|
} else {
|
|
callback(false, 'Unexpected answer from server when fetching object.')
|
|
console.log(answer)
|
|
}
|
|
} else if (request.readyState == 4) {
|
|
callback(false, 'Server error when fetching object (' + request.status + ').')
|
|
}
|
|
}
|
|
request.open('GET', id, true)
|
|
const token = TokenCollection.get(id)
|
|
if (token) {
|
|
request.setRequestHeader('Authorization', 'Bearer ' + token)
|
|
}
|
|
request.setRequestHeader('Content-Type', 'application/activity+json')
|
|
request.setRequestHeader('Accept', 'application/activity+json')
|
|
request.send()
|
|
},
|
|
// Build from type name
|
|
_type_from_name: {
|
|
// Core types
|
|
'Object': ASObject,
|
|
'Link': ASLink,
|
|
'Activity': ASActivity,
|
|
'IntransitiveActivity': ASIntransitiveActivity,
|
|
'Collection': ASCollection,
|
|
'OrderedCollection': ASOrderedCollection,
|
|
'CollectionPage': ASCollectionPage,
|
|
'OrderedCollectionPage': ASOrderedCollectionPage,
|
|
'Actor': ASActor,
|
|
// Activity Types
|
|
'Accept': ASAccept,
|
|
'Add': ASAdd,
|
|
'Announce': ASAnnounce,
|
|
'Arrive': ASArrive,
|
|
'Block': ASBlock,
|
|
'Create': ASCreate,
|
|
'Delete': ASDelete,
|
|
'Dislike': ASDislike,
|
|
'Flag': ASFlag,
|
|
'Follow': ASFollow,
|
|
'Ignore': ASIgnore,
|
|
'Invite': ASInvite,
|
|
'Join': ASJoin,
|
|
'Leave': ASLeave,
|
|
'Like': ASLike,
|
|
'Listen': ASListen,
|
|
'Move': ASMove,
|
|
'Offer': ASOffer,
|
|
'Question': ASQuestion,
|
|
'Reject': ASReject,
|
|
'Read': ASRead,
|
|
'Remove': ASRemove,
|
|
'TentativeReject': ASTentativeReject,
|
|
'TentativeAccept': ASTentativeAccept,
|
|
'Travel': ASTravel,
|
|
'Undo': ASUndo,
|
|
'Update': ASUpdate,
|
|
'View': ASView,
|
|
// Actor Types
|
|
'Application': ASApplication,
|
|
'Group': ASGroup,
|
|
'Organization': ASOrganization,
|
|
'Person': ASPerson,
|
|
'Service': ASService,
|
|
// Object Types
|
|
'Article': ASArticle,
|
|
'Audio': ASAudio,
|
|
'Document': ASDocument,
|
|
'Event': ASEvent,
|
|
'Image': ASImage,
|
|
'Note': ASNote,
|
|
'Page': ASPage,
|
|
'Place': ASPlace,
|
|
'Profile': ASProfile,
|
|
'Relationship': ASRelationship,
|
|
'Tombstone': ASTombstone,
|
|
'Video': ASVideo,
|
|
// Link Types
|
|
'Mention': ASMention,
|
|
},
|
|
// Add additionnal types
|
|
addType: function(name, type) {
|
|
Fetcher._type_from_name[name] = type
|
|
},
|
|
// Build an object of the right type from its json representation
|
|
fromJson: function(raw) {
|
|
const result = Fetcher._type_from_name[raw.type] ? new (Fetcher._type_from_name[raw.type])() : new ASBase()
|
|
result.fromJson(raw)
|
|
return result
|
|
}
|
|
}
|
|
|
|
// ASBase prototype
|
|
ASBase.prototype = {
|
|
// Raw representation of the element
|
|
_raw: undefined,
|
|
// Description of the properties
|
|
// Array of properties that do not need to be fetched
|
|
// Those are directly copied from/to raw into the object
|
|
// This array should be overwritten when inheriting prototypes (by completing it)
|
|
_alwaysAvailable: ['id', 'type'],
|
|
// Array of properties that may need to be fetched
|
|
// Those need an additional fetch from raw, and special handling when converting back to raw
|
|
// This array should be overwritten when inheriting prototypes (by completing it)
|
|
_mayNeedFetch: [ /*empty*/ ],
|
|
// Properties
|
|
id: undefined, // Id of element
|
|
type: undefined, // Type of element
|
|
// Methods
|
|
// Load from a Json representation
|
|
fromJson: function(raw) {
|
|
this._raw = raw
|
|
// copy everything expected from raw
|
|
this._alwaysAvailable.map(function(elem) {
|
|
this[elem] = raw[elem]
|
|
}.bind(this))
|
|
// Copy everything expected from raw, fetchAttribute should be used to retrieve the values when needed
|
|
this._mayNeedFetch.map(function(elem) {
|
|
this[elem] = raw[elem]
|
|
}.bind(this))
|
|
},
|
|
// Convert to Json representation
|
|
updateRaw: function() {
|
|
this._raw = {}
|
|
// Copy everything of _alwaysAvailable into raw
|
|
this._alwaysAvailable.map(function(elem) {
|
|
this._raw[elem] = this[elem]
|
|
}.bind(this))
|
|
// Use getAttributeRawValue for everything of _mayNeedFetch
|
|
this._mayNeedFetch.map(function(elem) {
|
|
this._raw[elem] = this.getAttributeRawValue(this[elem])
|
|
}.bind(this))
|
|
},
|
|
// Utilitary function to use for updating raw data
|
|
// Returns either:
|
|
// - val.id if it exists
|
|
// - val._raw if val.updateRaw exists, after a call to val.updateRaw()
|
|
// - val in other cases
|
|
getAttributeRawValue: function(val) {
|
|
if (val && val.id) {
|
|
return val.id
|
|
} else if (val && val.updateRaw) {
|
|
val.updateRaw()
|
|
return val._raw
|
|
} else {
|
|
return val
|
|
}
|
|
},
|
|
// For fetching properties
|
|
// Fetch a property
|
|
// After fromJson has been called, the attributes may not be yet in a usable format, notably those which can be objects
|
|
// This method fetch and convert an attribute in a usable format
|
|
// Callback signature is function(load_ok, failure_message)
|
|
// Note: done this way to avoid fetching all resources in fromJson, but only when they are needed
|
|
fetchAttribute: function(attribute_name, callback) {
|
|
this._fetchAttribute(attribute_name, Fetcher.get, callback)
|
|
},
|
|
refreshAttribute: function(attribute_name, callback) {
|
|
this._fetchAttribute(attribute_name, Fetcher.refresh, callback)
|
|
},
|
|
// Private method, with fetcher function to call
|
|
_fetchAttribute: function(attribute_name, fetch_func, callback) {
|
|
const attribute_value = this[attribute_name]
|
|
if (this._alwaysAvailable.includes(attribute_name)) {
|
|
// Those attributes are always available in a usable format, no need to fetch
|
|
callback(true, undefined)
|
|
} else if (!this._mayNeedFetch.includes(attribute_name)) {
|
|
// Invalid call: the asked attribute cannot be fetched
|
|
callback(false, 'Invalid argument to fetchAttribute: ' + attribute_name + ' cannot be fetched.')
|
|
} else if ((typeof attribute_value === undefined) || (typeof attribute_value === null)) {
|
|
// Nothing to do
|
|
callback(true, undefined)
|
|
} else if (Array.isArray(attribute_value)) {
|
|
// Attribute is an array of elements. Each element should be converted.
|
|
this._fetchAndConvertAllAttributeValue(attribute_value.values(), fetch_func, function(load_ok, fetched_value, failure_message) {
|
|
// Update value of attribute
|
|
this[attribute_name] = fetched_value
|
|
callback(load_ok, failure_message)
|
|
}.bind(this))
|
|
} else if ((typeof attribute_value === 'object') && (attribute_value._raw !== undefined)) {
|
|
// Attribute has already been fetched
|
|
callback(true, undefined)
|
|
} else {
|
|
// Convertion needed
|
|
this._fetchAndConvertAttributeValue(attribute_value, fetch_func, function(load_ok, fetched_value, failure_message) {
|
|
// Update value of attribute
|
|
this[attribute_name] = fetched_value
|
|
callback(load_ok, failure_message)
|
|
}.bind(this))
|
|
}
|
|
},
|
|
// Fetch all elements of an array iterator to populate a result array
|
|
// Callback signature is function(load_ok, fetched_value, failure_message)
|
|
_fetchAndConvertAllAttributeValue: function(iter, fetch_func, callback, ret_value, previous_errors) {
|
|
const next = iter.next()
|
|
if (next.done) {
|
|
callback(true, ret_value, (previous_errors === '') ? undefined : previous_errors)
|
|
} else {
|
|
this._fetchAndConvertAttributeValue(next.value, fetch_func, function(load_ok, fetched_value, failure_message) {
|
|
var values = ret_value ? ret_value : []
|
|
const msg_errors = (previous_errors ? previous_errors : '') + (load_ok ? '' : '<br/>' + failure_message)
|
|
if (load_ok) {
|
|
values.push(fetched_value)
|
|
} else {
|
|
// Don't stop at first error, but cumulate error messages
|
|
console.log(failure_message)
|
|
}
|
|
// Next
|
|
this._fetchAndConvertAllAttributeValue(iter, fetch_func, callback, values, msg_errors)
|
|
}.bind(this))
|
|
}
|
|
},
|
|
// Fetch an attribute value
|
|
// Callback signature is function(load_ok, fetched_value, failure_message)
|
|
_fetchAndConvertAttributeValue: function(attribute_value, fetch_func, callback) {
|
|
if ((attribute_value === undefined) || (attribute_value === null)) {
|
|
// attribute is not present, return it as is
|
|
callback(true, attribute_value, undefined)
|
|
} else if (typeof attribute_value === 'object') {
|
|
// In object format already, as a Json value,
|
|
// use Fetcher.fromJson
|
|
callback(true, Fetcher.fromJson(attribute_value), undefined)
|
|
} else if (typeof attribute_value === 'string') {
|
|
// Link => fetch value
|
|
fetch_func(attribute_value, function(load_ok, obj, failure_message) {
|
|
if (load_ok) {
|
|
callback(true, obj, undefined)
|
|
} else {
|
|
callback(false, undefined, failure_message)
|
|
}
|
|
})
|
|
} else {
|
|
// Should not happen
|
|
console.log(attribute_value)
|
|
callback(false, undefined, 'Unexpected type of attribute.')
|
|
}
|
|
},
|
|
// Fetch several attributes at the same time
|
|
// Callback signature is function(load_ok, failure_message)
|
|
fetchAttributeList: function (attribute_lst, callback) {
|
|
this._fetchAttributeList(attribute_lst, Fetcher.get, callback)
|
|
},
|
|
refreshAttributeList: function (attribute_lst, callback) {
|
|
this._fetchAttributeList(attribute_lst, Fetcher.refresh, callback)
|
|
},
|
|
_fetchAttributeList: function (attribute_lst, fetch_func, callback) {
|
|
this._fetchAttributeListIter(attribute_lst.values(), fetch_func, callback, undefined)
|
|
},
|
|
//
|
|
_fetchAttributeListIter: function (attribute_lst, fetch_func, callback, previous_errors) {
|
|
const next = attribute_lst.next()
|
|
if (next.done) {
|
|
callback(true, (previous_errors === '') ? undefined : previous_errors)
|
|
} else {
|
|
this._fetchAttribute(next.value, fetch_func, function(load_ok, failure_message) {
|
|
const msg_errors = (previous_errors ? previous_errors : '') + (load_ok ? '' : '<br/>' + failure_message)
|
|
if (!load_ok) {
|
|
// Don't stop at first error, but cumulate error messages
|
|
console.log(failure_message)
|
|
}
|
|
// Next
|
|
this._fetchAttributeListIter(attribute_lst, fetch_func, callback, msg_errors)
|
|
}.bind(this))
|
|
}
|
|
}
|
|
}
|
|
|
|
// ASObject prototype
|
|
ASObject.prototype = Object.create(ASBase.prototype)
|
|
Object.assign(ASObject.prototype,
|
|
{
|
|
// Attributes
|
|
attachment: undefined,
|
|
attributedTo: undefined,
|
|
audience: undefined,
|
|
content: undefined,
|
|
context: undefined,
|
|
name: undefined,
|
|
endTime: undefined,
|
|
generator: undefined,
|
|
icon: undefined,
|
|
image: undefined,
|
|
inReplyTo: undefined,
|
|
location: undefined,
|
|
preview: undefined,
|
|
published: undefined,
|
|
replies: undefined,
|
|
startTime: undefined,
|
|
summary: undefined,
|
|
tag: undefined,
|
|
updated: undefined,
|
|
url: undefined,
|
|
to: undefined,
|
|
bto: undefined,
|
|
cc: undefined,
|
|
bcc: undefined,
|
|
mediaType: undefined,
|
|
duration: undefined,
|
|
// defined in ActivityPub
|
|
source: undefined,
|
|
likes: undefined,
|
|
shares: undefined,
|
|
// Array of properties that do not need to be fetched
|
|
// This array should be overwritten when inheriting prototypes (by completing it)
|
|
_alwaysAvailable: ASBase.prototype._alwaysAvailable.concat([
|
|
'content', 'name', 'endTime', 'published', 'startTime', 'summary', 'updated', 'url',
|
|
'mediaType', 'duration',
|
|
]),
|
|
// Array of properties that may need to be fetched
|
|
// This array should be overwritten when inheriting prototypes (by completing it)
|
|
_mayNeedFetch: ASBase.prototype._mayNeedFetch.concat([
|
|
'attachment', 'attributedTo', 'audience', 'context', 'generator', 'icon', 'image', 'inReplyTo',
|
|
'location', 'preview', 'replies', 'tag', 'to', 'bto', 'cc', 'bcc', 'source', 'likes', 'shares'
|
|
]),
|
|
})
|
|
ASObject.prototype.constructor = ASObject
|
|
|
|
// ASLink prototype
|
|
ASLink.prototype = Object.create(ASBase.prototype)
|
|
Object.assign(ASLink.prototype,
|
|
{
|
|
// Attributes
|
|
href: undefined,
|
|
rel: undefined,
|
|
mediaType: undefined,
|
|
name: undefined,
|
|
hreflang: undefined,
|
|
height: undefined,
|
|
width: undefined,
|
|
preview: undefined,
|
|
// Array of properties that do not need to be fetched
|
|
// This array should be overwritten when inheriting prototypes (by completing it)
|
|
_alwaysAvailable: ASBase.prototype._alwaysAvailable.concat([
|
|
'href', 'rel', 'mediaType', 'name', 'hreflang', 'height', 'width',
|
|
]),
|
|
// Array of properties that may need to be fetched
|
|
// This array should be overwritten when inheriting prototypes (by completing it)
|
|
_mayNeedFetch: ASBase.prototype._mayNeedFetch.concat([
|
|
'preview',
|
|
]),
|
|
})
|
|
ASLink.prototype.constructor = ASLink
|
|
|
|
// ASActivity prototype
|
|
ASActivity.prototype = Object.create(ASObject.prototype)
|
|
Object.assign(ASActivity.prototype,
|
|
{
|
|
// Attributes
|
|
actor: undefined,
|
|
object: undefined,
|
|
target: undefined,
|
|
result: undefined,
|
|
origin: undefined,
|
|
instrument: undefined,
|
|
// Array of properties that do not need to be fetched
|
|
// This array should be overwritten when inheriting prototypes (by completing it)
|
|
_alwaysAvailable: ASObject.prototype._alwaysAvailable.concat([
|
|
]),
|
|
// Array of properties that may need to be fetched
|
|
// This array should be overwritten when inheriting prototypes (by completing it)
|
|
_mayNeedFetch: ASObject.prototype._mayNeedFetch.concat([
|
|
'actor', 'object', 'target', 'result', 'origin', 'instrument',
|
|
]),
|
|
})
|
|
ASActivity.prototype.constructor = ASActivity
|
|
|
|
// ASIntransitiveActivity prototype
|
|
// Note: the object field is not removed from ASActivity
|
|
ASIntransitiveActivity.prototype = Object.create(ASActivity.prototype)
|
|
ASIntransitiveActivity.prototype.constructor = ASIntransitiveActivity
|
|
|
|
// ASCollection prototype
|
|
ASCollection.prototype = Object.create(ASObject.prototype)
|
|
Object.assign(ASCollection.prototype,
|
|
{
|
|
// Attributes
|
|
totalItems: undefined,
|
|
current: undefined,
|
|
first: undefined,
|
|
last: undefined,
|
|
items: undefined,
|
|
// Array of properties that do not need to be fetched
|
|
// This array should be overwritten when inheriting prototypes (by completing it)
|
|
_alwaysAvailable: ASObject.prototype._alwaysAvailable.concat([
|
|
'totalItems',
|
|
]),
|
|
// Array of properties that may need to be fetched
|
|
// This array should be overwritten when inheriting prototypes (by completing it)
|
|
_mayNeedFetch: ASObject.prototype._mayNeedFetch.concat([
|
|
'current', 'first', 'last', 'items'
|
|
]),
|
|
})
|
|
ASCollection.prototype.constructor = ASCollection
|
|
|
|
// ASOrderedCollection prototype
|
|
ASOrderedCollection.prototype = Object.create(ASCollection.prototype)
|
|
Object.assign(ASOrderedCollection.prototype,
|
|
{
|
|
// Attributes
|
|
orderedItems: undefined, // Shouldn't be needed, as it has the same meaning as 'items' of ASCollection, but present in implementations
|
|
// Array of properties that do not need to be fetched
|
|
// This array should be overwritten when inheriting prototypes (by completing it)
|
|
_alwaysAvailable: ASCollection.prototype._alwaysAvailable.concat([
|
|
]),
|
|
// Array of properties that may need to be fetched
|
|
// This array should be overwritten when inheriting prototypes (by completing it)
|
|
_mayNeedFetch: ASCollection.prototype._mayNeedFetch.concat([
|
|
'orderedItems',
|
|
]),
|
|
})
|
|
ASOrderedCollection.prototype.constructor = ASOrderedCollection
|
|
|
|
// ASCollectionPage prototype
|
|
ASCollectionPage.prototype = Object.create(ASCollection.prototype)
|
|
Object.assign(ASCollectionPage.prototype,
|
|
{
|
|
// Attributes
|
|
partOf: undefined,
|
|
next: undefined,
|
|
prev: undefined,
|
|
// Array of properties that do not need to be fetched
|
|
// This array should be overwritten when inheriting prototypes (by completing it)
|
|
_alwaysAvailable: ASCollection.prototype._alwaysAvailable.concat([
|
|
]),
|
|
// Array of properties that may need to be fetched
|
|
// This array should be overwritten when inheriting prototypes (by completing it)
|
|
_mayNeedFetch: ASCollection.prototype._mayNeedFetch.concat([
|
|
'partOf', 'next', 'prev',
|
|
]),
|
|
})
|
|
ASCollectionPage.prototype.constructor = ASCollectionPage
|
|
|
|
// ASOrderedCollectionPage prototype
|
|
// Specification says that it inherits from both ASCollectionPage and ASOrderedCollection,
|
|
ASOrderedCollectionPage.prototype = Object.create(ASCollectionPage.prototype)
|
|
Object.assign(ASOrderedCollectionPage.prototype, ASOrderedCollection.prototype)
|
|
// Helping function for removing duplicates
|
|
const unique = function(arr) {
|
|
return arr.filter(function (elem, idx) { return idx === arr.indexOf(elem) })
|
|
}
|
|
Object.assign(ASOrderedCollectionPage.prototype,
|
|
{
|
|
// Attributes
|
|
startIndex: undefined,
|
|
// Array of properties that do not need to be fetched
|
|
// This array should be overwritten when inheriting prototypes (by completing it)
|
|
_alwaysAvailable: unique(ASOrderedCollection.prototype._alwaysAvailable.concat(ASCollectionPage.prototype._alwaysAvailable.concat([
|
|
'startIndex',
|
|
]))),
|
|
// Array of properties that may need to be fetched
|
|
// This array should be overwritten when inheriting prototypes (by completing it)
|
|
_mayNeedFetch: unique(ASOrderedCollection.prototype._mayNeedFetch.concat(ASCollectionPage.prototype._mayNeedFetch.concat([
|
|
]))),
|
|
})
|
|
ASOrderedCollectionPage.prototype.constructor = ASOrderedCollectionPage
|
|
|
|
// ASActor
|
|
// Defined from the ActivityPub spec, which adds fields to actor types
|
|
ASActor.prototype = Object.create(ASObject.prototype)
|
|
Object.assign(ASActor.prototype,
|
|
{
|
|
// Attributes
|
|
inbox: undefined,
|
|
outbox: undefined,
|
|
following: undefined,
|
|
followers: undefined,
|
|
liked: undefined,
|
|
streams: undefined,
|
|
preferredUsername: undefined,
|
|
endpoints: undefined,
|
|
// Array of properties that do not need to be fetched
|
|
// This array should be overwritten when inheriting prototypes (by completing it)
|
|
_alwaysAvailable: ASObject.prototype._alwaysAvailable.concat([
|
|
'preferredUsername', 'endpoints',
|
|
// Note: endpoints should be in the _mayNeedFetch, but it is usually not represented with a vocabulary object, so no type associated
|
|
// However, in the observed implementations, this structure is always provided in the actor
|
|
]),
|
|
// Array of properties that may need to be fetched
|
|
// This array should be overwritten when inheriting prototypes (by completing it)
|
|
_mayNeedFetch: ASObject.prototype._mayNeedFetch.concat([
|
|
'inbox', 'outbox', 'following', 'followers', 'liked', 'streams',
|
|
]),
|
|
})
|
|
ASActor.prototype.constructor = ASActor
|
|
|
|
// Extended Types
|
|
// Activity Types
|
|
|
|
// ASAccept prototype
|
|
ASAccept.prototype = Object.create(ASActivity.prototype)
|
|
ASAccept.prototype.constructor = ASAccept
|
|
|
|
// ASTentativeAccept prototype
|
|
ASTentativeAccept.prototype = Object.create(ASAccept.prototype)
|
|
ASAccept.prototype.constructor = ASAccept
|
|
|
|
// ASAdd prototype
|
|
ASAdd.prototype = Object.create(ASActivity.prototype)
|
|
ASAdd.prototype.constructor = ASAdd
|
|
|
|
// ASArrive prototype
|
|
ASArrive.prototype = Object.create(ASIntransitiveActivity.prototype)
|
|
ASArrive.prototype.constructor = ASArrive
|
|
|
|
// ASCreate prototype
|
|
ASCreate.prototype = Object.create(ASActivity.prototype)
|
|
ASCreate.prototype.constructor = ASCreate
|
|
|
|
// ASDelete prototype
|
|
ASDelete.prototype = Object.create(ASActivity.prototype)
|
|
ASDelete.prototype.constructor = ASDelete
|
|
|
|
// ASFollow prototype
|
|
ASFollow.prototype = Object.create(ASActivity.prototype)
|
|
ASFollow.prototype.constructor = ASFollow
|
|
|
|
// ASIgnore prototype
|
|
ASIgnore.prototype = Object.create(ASActivity.prototype)
|
|
ASIgnore.prototype.constructor = ASIgnore
|
|
|
|
// ASJoin prototype
|
|
ASJoin.prototype = Object.create(ASActivity.prototype)
|
|
ASJoin.prototype.constructor = ASJoin
|
|
|
|
// ASLeave prototype
|
|
ASLeave.prototype = Object.create(ASActivity.prototype)
|
|
ASLeave.prototype.constructor = ASLeave
|
|
|
|
// ASLike prototype
|
|
ASLike.prototype = Object.create(ASActivity.prototype)
|
|
ASLike.prototype.constructor = ASLike
|
|
|
|
// ASOffer prototype
|
|
ASOffer.prototype = Object.create(ASActivity.prototype)
|
|
ASOffer.prototype.constructor = ASOffer
|
|
|
|
// ASInvite prototype
|
|
ASInvite.prototype = Object.create(ASOffer.prototype)
|
|
ASInvite.prototype.constructor = ASInvite
|
|
|
|
// ASReject prototype
|
|
ASReject.prototype = Object.create(ASActivity.prototype)
|
|
ASReject.prototype.constructor = ASReject
|
|
|
|
// ASTentativeReject prototype
|
|
ASTentativeReject.prototype = Object.create(ASReject.prototype)
|
|
ASTentativeReject.prototype.constructor = ASTentativeReject
|
|
|
|
// ASRemove prototype
|
|
ASRemove.prototype = Object.create(ASActivity.prototype)
|
|
ASRemove.prototype.constructor = ASRemove
|
|
|
|
// ASUndo prototype
|
|
ASUndo.prototype = Object.create(ASActivity.prototype)
|
|
ASUndo.prototype.constructor = ASUndo
|
|
|
|
// ASUpdate prototype
|
|
ASUpdate.prototype = Object.create(ASActivity.prototype)
|
|
ASUpdate.prototype.constructor = ASUpdate
|
|
|
|
// ASView prototype
|
|
ASView.prototype = Object.create(ASActivity.prototype)
|
|
ASView.prototype.constructor = ASView
|
|
|
|
// ASListen prototype
|
|
ASListen.prototype = Object.create(ASActivity.prototype)
|
|
ASListen.prototype.constructor = ASListen
|
|
|
|
// ASRead prototype
|
|
ASRead.prototype = Object.create(ASActivity.prototype)
|
|
ASRead.prototype.constructor = ASRead
|
|
|
|
// ASMove prototype
|
|
ASMove.prototype = Object.create(ASActivity.prototype)
|
|
ASMove.prototype.constructor = ASMove
|
|
|
|
// ASTravel prototype
|
|
ASTravel.prototype = Object.create(ASIntransitiveActivity.prototype)
|
|
ASTravel.prototype.constructor = ASTravel
|
|
|
|
// ASAnnounce prototype
|
|
ASAnnounce.prototype = Object.create(ASActivity.prototype)
|
|
ASAnnounce.prototype.constructor = ASAnnounce
|
|
|
|
// ASBlock prototype
|
|
ASBlock.prototype = Object.create(ASIgnore.prototype)
|
|
ASBlock.prototype.constructor = ASBlock
|
|
|
|
// ASFlag prototype
|
|
ASFlag.prototype = Object.create(ASActivity.prototype)
|
|
ASFlag.prototype.constructor = ASFlag
|
|
|
|
// ASDislike prototype
|
|
ASDislike.prototype = Object.create(ASActivity.prototype)
|
|
ASDislike.prototype.constructor = ASDislike
|
|
|
|
// ASQuestion prototype
|
|
ASQuestion.prototype = Object.create(ASIntransitiveActivity.prototype)
|
|
Object.assign(ASQuestion.prototype,
|
|
{
|
|
// Attributes
|
|
oneOf: undefined,
|
|
anyOf: undefined,
|
|
closed: undefined,
|
|
// Array of properties that do not need to be fetched
|
|
// This array should be overwritten when inheriting prototypes (by completing it)
|
|
_alwaysAvailable: ASIntransitiveActivity.prototype._alwaysAvailable.concat([
|
|
'closed',
|
|
]),
|
|
// Array of properties that may need to be fetched
|
|
// This array should be overwritten when inheriting prototypes (by completing it)
|
|
_mayNeedFetch: ASIntransitiveActivity.prototype._mayNeedFetch.concat([
|
|
'oneOf', 'anyOf',
|
|
]),
|
|
})
|
|
ASQuestion.prototype.constructor = ASQuestion
|
|
|
|
// Actor Types
|
|
// ASApplication prototype
|
|
ASApplication.prototype = Object.create(ASActor.prototype)
|
|
ASApplication.prototype.constructor = ASApplication
|
|
|
|
// ASGroup prototype
|
|
ASGroup.prototype = Object.create(ASActor.prototype)
|
|
ASGroup.prototype.constructor = ASGroup
|
|
|
|
// ASOrganization prototype
|
|
ASOrganization.prototype = Object.create(ASActor.prototype)
|
|
ASOrganization.prototype.constructor = ASOrganization
|
|
|
|
// ASPerson prototype
|
|
ASPerson.prototype = Object.create(ASActor.prototype)
|
|
ASPerson.prototype.constructor = ASPerson
|
|
|
|
// ASService prototype
|
|
ASService.prototype = Object.create(ASActor.prototype)
|
|
ASService.prototype.constructor = ASService
|
|
|
|
// ASRelationship prototype
|
|
ASRelationship.prototype = Object.create(ASObject.prototype)
|
|
Object.assign(ASRelationship.prototype,
|
|
{
|
|
// Attributes
|
|
subject: undefined,
|
|
object: undefined,
|
|
relationship: undefined,
|
|
// Array of properties that do not need to be fetched
|
|
// This array should be overwritten when inheriting prototypes (by completing it)
|
|
_alwaysAvailable: ASObject.prototype._alwaysAvailable.concat([
|
|
]),
|
|
// Array of properties that may need to be fetched
|
|
// This array should be overwritten when inheriting prototypes (by completing it)
|
|
_mayNeedFetch: ASObject.prototype._mayNeedFetch.concat([
|
|
'subject', 'object', 'relationship',
|
|
]),
|
|
})
|
|
ASRelationship.prototype.constructor = ASRelationship
|
|
|
|
// ASArticle prototype
|
|
ASArticle.prototype = Object.create(ASObject.prototype)
|
|
ASArticle.prototype.constructor = ASArticle
|
|
|
|
// ASDocument prototype
|
|
ASDocument.prototype = Object.create(ASObject.prototype)
|
|
ASDocument.prototype.constructor = ASDocument
|
|
|
|
// ASAudio prototype
|
|
ASAudio.prototype = Object.create(ASDocument.prototype)
|
|
ASAudio.prototype.constructor = ASAudio
|
|
|
|
// ASImage prototype
|
|
ASImage.prototype = Object.create(ASDocument.prototype)
|
|
ASImage.prototype.constructor = ASImage
|
|
|
|
// ASVideo prototype
|
|
ASVideo.prototype = Object.create(ASDocument.prototype)
|
|
ASVideo.prototype.constructor = ASVideo
|
|
|
|
// ASNote prototype
|
|
ASNote.prototype = Object.create(ASObject.prototype)
|
|
ASNote.prototype.constructor = ASNote
|
|
|
|
// ASPage prototype
|
|
ASPage.prototype = Object.create(ASDocument.prototype)
|
|
ASPage.prototype.constructor = ASPage
|
|
|
|
// ASEvent prototype
|
|
ASEvent.prototype = Object.create(ASObject.prototype)
|
|
ASEvent.prototype.constructor = ASEvent
|
|
|
|
// ASPlace prototype
|
|
ASPlace.prototype = Object.create(ASObject.prototype)
|
|
Object.assign(ASPlace.prototype,
|
|
{
|
|
// Attributes
|
|
accuracy: undefined,
|
|
altitude: undefined,
|
|
latitude: undefined,
|
|
longitude: undefined,
|
|
radius: undefined,
|
|
units: undefined,
|
|
// Array of properties that do not need to be fetched
|
|
// This array should be overwritten when inheriting prototypes (by completing it)
|
|
_alwaysAvailable: ASObject.prototype._alwaysAvailable.concat([
|
|
'accuracy', 'altitude', 'latitude', 'longitude',
|
|
'radius', 'units',
|
|
]),
|
|
// Array of properties that may need to be fetched
|
|
// This array should be overwritten when inheriting prototypes (by completing it)
|
|
_mayNeedFetch: ASObject.prototype._mayNeedFetch.concat([
|
|
]),
|
|
})
|
|
ASPlace.prototype.constructor = ASPlace
|
|
|
|
// ASProfile prototype
|
|
ASProfile.prototype = Object.create(ASObject.prototype)
|
|
Object.assign(ASProfile.prototype,
|
|
{
|
|
// Attributes
|
|
describes: undefined,
|
|
// Array of properties that do not need to be fetched
|
|
// This array should be overwritten when inheriting prototypes (by completing it)
|
|
_alwaysAvailable: ASObject.prototype._alwaysAvailable.concat([
|
|
]),
|
|
// Array of properties that may need to be fetched
|
|
// This array should be overwritten when inheriting prototypes (by completing it)
|
|
_mayNeedFetch: ASObject.prototype._mayNeedFetch.concat([
|
|
'describes'
|
|
]),
|
|
})
|
|
ASProfile.prototype.constructor = ASProfile
|
|
|
|
// ASTombstone prototype
|
|
ASTombstone.prototype = Object.create(ASObject.prototype)
|
|
Object.assign(ASTombstone.prototype,
|
|
{
|
|
// Attributes
|
|
formerType: undefined,
|
|
deleted: undefined,
|
|
// Array of properties that do not need to be fetched
|
|
// This array should be overwritten when inheriting prototypes (by completing it)
|
|
_alwaysAvailable: ASObject.prototype._alwaysAvailable.concat([
|
|
'formerType', 'deleted',
|
|
]),
|
|
// Array of properties that may need to be fetched
|
|
// This array should be overwritten when inheriting prototypes (by completing it)
|
|
_mayNeedFetch: ASObject.prototype._mayNeedFetch.concat([
|
|
]),
|
|
})
|
|
ASTombstone.prototype.constructor = ASTombstone
|
|
|
|
// Link Types
|
|
// ASMention prototype
|
|
ASMention.prototype = Object.create(ASLink.prototype)
|
|
ASMention.prototype.constructor = ASMention
|
|
|
|
////
|
|
// Exported structures
|
|
export {
|
|
// Fetcher
|
|
Fetcher,
|
|
// Core types
|
|
ASObject,
|
|
ASLink,
|
|
ASActivity,
|
|
ASIntransitiveActivity,
|
|
ASCollection,
|
|
ASOrderedCollection,
|
|
ASCollectionPage,
|
|
ASOrderedCollectionPage,
|
|
ASActor,
|
|
// Activity types
|
|
ASAccept,
|
|
ASAdd,
|
|
ASAnnounce,
|
|
ASArrive,
|
|
ASBlock,
|
|
ASCreate,
|
|
ASDelete,
|
|
ASDislike,
|
|
ASFlag,
|
|
ASFollow,
|
|
ASIgnore,
|
|
ASInvite,
|
|
ASJoin,
|
|
ASLeave,
|
|
ASLike,
|
|
ASListen,
|
|
ASMove,
|
|
ASOffer,
|
|
ASQuestion,
|
|
ASReject,
|
|
ASRead,
|
|
ASRemove,
|
|
ASTentativeReject,
|
|
ASTentativeAccept,
|
|
ASTravel,
|
|
ASUpdate,
|
|
ASView,
|
|
// Actor types
|
|
ASApplication,
|
|
ASGroup,
|
|
ASOrganization,
|
|
ASPerson,
|
|
ASService,
|
|
// Object types
|
|
ASArticle,
|
|
ASAudio,
|
|
ASDocument,
|
|
ASImage,
|
|
ASNote,
|
|
ASPage,
|
|
ASPlace,
|
|
ASProfile,
|
|
ASRelationship,
|
|
ASTombstone,
|
|
ASVideo,
|
|
// Link types
|
|
ASMention,
|
|
}
|