Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Pleroma
pleroma
Commits
20baa2ea
Commit
20baa2ea
authored
May 06, 2020
by
lain
Browse files
ChatMessages: Add attachments.
parent
205313e5
Pipeline
#25363
failed with stages
in 7 minutes and 12 seconds
Changes
14
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
lib/pleroma/web/activity_pub/builder.ex
View file @
20baa2ea
...
...
@@ -23,17 +23,28 @@ def create(actor, object, recipients) do
},
[]}
end
def
chat_message
(
actor
,
recipient
,
content
)
do
{
:ok
,
%{
"id"
=>
Utils
.
generate_object_id
(),
"actor"
=>
actor
.
ap_id
,
"type"
=>
"ChatMessage"
,
"to"
=>
[
recipient
],
"content"
=>
content
,
"published"
=>
DateTime
.
utc_now
()
|>
DateTime
.
to_iso8601
(),
"emoji"
=>
Emoji
.
Formatter
.
get_emoji_map
(
content
)
},
[]}
def
chat_message
(
actor
,
recipient
,
content
,
opts
\\
[])
do
basic
=
%{
"id"
=>
Utils
.
generate_object_id
(),
"actor"
=>
actor
.
ap_id
,
"type"
=>
"ChatMessage"
,
"to"
=>
[
recipient
],
"content"
=>
content
,
"published"
=>
DateTime
.
utc_now
()
|>
DateTime
.
to_iso8601
(),
"emoji"
=>
Emoji
.
Formatter
.
get_emoji_map
(
content
)
}
case
opts
[
:attachment
]
do
%
Object
{
data:
attachment_data
}
->
{
:ok
,
Map
.
put
(
basic
,
"attachment"
,
attachment_data
),
[]
}
_
->
{
:ok
,
basic
,
[]}
end
end
@spec
like
(
User
.
t
(),
Object
.
t
())
::
{
:ok
,
map
(),
keyword
()}
...
...
lib/pleroma/web/activity_pub/object_validator.ex
View file @
20baa2ea
...
...
@@ -63,11 +63,18 @@ def stringify_keys(%{__struct__: _} = object) do
|>
stringify_keys
end
def
stringify_keys
(
object
)
do
def
stringify_keys
(
object
)
when
is_map
(
object
)
do
object
|>
Map
.
new
(
fn
{
key
,
val
}
->
{
to_string
(
key
),
val
}
end
)
|>
Map
.
new
(
fn
{
key
,
val
}
->
{
to_string
(
key
),
stringify_keys
(
val
)
}
end
)
end
def
stringify_keys
(
object
)
when
is_list
(
object
)
do
object
|>
Enum
.
map
(
&
stringify_keys
/
1
)
end
def
stringify_keys
(
object
),
do
:
object
def
fetch_actor
(
object
)
do
with
{
:ok
,
actor
}
<-
Types
.
ObjectID
.
cast
(
object
[
"actor"
])
do
User
.
get_or_fetch_by_ap_id
(
actor
)
...
...
lib/pleroma/web/activity_pub/object_validators/attachment_validator.ex
0 → 100644
View file @
20baa2ea
# Pleroma: A lightweight social networking server
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule
Pleroma
.
Web
.
ActivityPub
.
ObjectValidators
.
AttachmentValidator
do
use
Ecto
.
Schema
alias
Pleroma
.
Web
.
ActivityPub
.
ObjectValidators
.
UrlObjectValidator
import
Ecto
.
Changeset
@primary_key
false
embedded_schema
do
field
(
:type
,
:string
)
field
(
:mediaType
,
:string
)
field
(
:name
,
:string
)
embeds_many
(
:url
,
UrlObjectValidator
)
end
def
cast_and_validate
(
data
)
do
data
|>
cast_data
()
|>
validate_data
()
end
def
cast_data
(
data
)
do
%
__MODULE__
{}
|>
changeset
(
data
)
end
def
changeset
(
struct
,
data
)
do
data
=
data
|>
fix_media_type
()
|>
fix_url
()
struct
|>
cast
(
data
,
[
:type
,
:mediaType
,
:name
])
|>
cast_embed
(
:url
,
required:
true
)
end
def
fix_media_type
(
data
)
do
data
|>
Map
.
put_new
(
"mediaType"
,
data
[
"mimeType"
])
end
def
fix_url
(
data
)
do
case
data
[
"url"
]
do
url
when
is_binary
(
url
)
->
data
|>
Map
.
put
(
"url"
,
[
%{
"href"
=>
url
,
"type"
=>
"Link"
,
"mediaType"
=>
data
[
"mediaType"
]
}
]
)
_
->
data
end
end
def
validate_data
(
cng
)
do
cng
|>
validate_required
([
:mediaType
,
:url
,
:type
])
end
end
lib/pleroma/web/activity_pub/object_validators/chat_message_validator.ex
View file @
20baa2ea
...
...
@@ -7,6 +7,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ChatMessageValidator do
alias
Pleroma
.
User
alias
Pleroma
.
Web
.
ActivityPub
.
ObjectValidators
.
Types
alias
Pleroma
.
Web
.
ActivityPub
.
ObjectValidators
.
AttachmentValidator
import
Ecto
.
Changeset
import
Pleroma
.
Web
.
ActivityPub
.
Transmogrifier
,
only:
[
fix_emoji:
1
]
...
...
@@ -22,6 +23,8 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ChatMessageValidator do
field
(
:actor
,
Types
.
ObjectID
)
field
(
:published
,
Types
.
DateTime
)
field
(
:emoji
,
:map
,
default:
%{})
embeds_one
(
:attachment
,
AttachmentValidator
)
end
def
cast_and_apply
(
data
)
do
...
...
@@ -51,7 +54,8 @@ def changeset(struct, data) do
data
=
fix
(
data
)
struct
|>
cast
(
data
,
__schema__
(
:fields
))
|>
cast
(
data
,
List
.
delete
(
__schema__
(
:fields
),
:attachment
))
|>
cast_embed
(
:attachment
)
end
def
validate_data
(
data_cng
)
do
...
...
lib/pleroma/web/activity_pub/object_validators/url_object_validator.ex
0 → 100644
View file @
20baa2ea
defmodule
Pleroma
.
Web
.
ActivityPub
.
ObjectValidators
.
UrlObjectValidator
do
use
Ecto
.
Schema
alias
Pleroma
.
Web
.
ActivityPub
.
ObjectValidators
.
Types
import
Ecto
.
Changeset
@primary_key
false
embedded_schema
do
field
(
:type
,
:string
)
field
(
:href
,
Types
.
Uri
)
field
(
:mediaType
,
:string
)
end
def
changeset
(
struct
,
data
)
do
struct
|>
cast
(
data
,
__schema__
(
:fields
))
|>
validate_required
([
:type
,
:href
,
:mediaType
])
end
end
lib/pleroma/web/api_spec/operations/chat_operation.ex
View file @
20baa2ea
...
...
@@ -236,7 +236,8 @@ def chat_message_create do
description:
"POST body for creating an chat message"
,
type:
:object
,
properties:
%{
content:
%
Schema
{
type:
:string
,
description:
"The content of your message"
}
content:
%
Schema
{
type:
:string
,
description:
"The content of your message"
},
media_id:
%
Schema
{
type:
:string
,
description:
"The id of an upload"
}
},
required:
[
:content
],
example:
%{
...
...
lib/pleroma/web/api_spec/schemas/chat_message.ex
View file @
20baa2ea
...
...
@@ -17,7 +17,8 @@ defmodule Pleroma.Web.ApiSpec.Schemas.ChatMessage do
chat_id:
%
Schema
{
type:
:string
},
content:
%
Schema
{
type:
:string
},
created_at:
%
Schema
{
type:
:string
,
format:
:"date-time"
},
emojis:
%
Schema
{
type:
:array
}
emojis:
%
Schema
{
type:
:array
},
attachment:
%
Schema
{
type:
:object
,
nullable:
true
}
},
example:
%{
"account_id"
=>
"someflakeid"
,
...
...
@@ -32,7 +33,8 @@ defmodule Pleroma.Web.ApiSpec.Schemas.ChatMessage do
"url"
=>
"https://dontbulling.me/emoji/Firefox.gif"
}
],
"id"
=>
"14"
"id"
=>
"14"
,
"attachment"
=>
nil
}
})
end
lib/pleroma/web/common_api/common_api.ex
View file @
20baa2ea
...
...
@@ -25,14 +25,16 @@ defmodule Pleroma.Web.CommonAPI do
require
Pleroma
.
Constants
require
Logger
def
post_chat_message
(%
User
{}
=
user
,
%
User
{}
=
recipient
,
content
)
do
def
post_chat_message
(%
User
{}
=
user
,
%
User
{}
=
recipient
,
content
,
opts
\\
[]
)
do
with
:ok
<-
validate_chat_content_length
(
content
),
maybe_attachment
<-
opts
[
:media_id
]
&&
Object
.
get_by_id
(
opts
[
:media_id
]),
{
_
,
{
:ok
,
chat_message_data
,
_meta
}}
<-
{
:build_object
,
Builder
.
chat_message
(
user
,
recipient
.
ap_id
,
content
|>
Formatter
.
html_escape
(
"text/plain"
)
content
|>
Formatter
.
html_escape
(
"text/plain"
),
attachment:
maybe_attachment
)},
{
_
,
{
:ok
,
create_activity_data
,
_meta
}}
<-
{
:build_create_activity
,
Builder
.
create
(
user
,
chat_message_data
,
[
recipient
.
ap_id
])},
...
...
lib/pleroma/web/pleroma_api/controllers/chat_controller.ex
View file @
20baa2ea
...
...
@@ -36,14 +36,16 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do
defdelegate
open_api_operation
(
action
),
to:
Pleroma
.
Web
.
ApiSpec
.
ChatOperation
def
post_chat_message
(
%{
body_params:
%{
content:
content
},
assigns:
%{
user:
%{
id:
user_id
}
=
user
}}
=
conn
,
%{
body_params:
%{
content:
content
}
=
params
,
assigns:
%{
user:
%{
id:
user_id
}
=
user
}}
=
conn
,
%{
id:
id
}
)
do
with
%
Chat
{}
=
chat
<-
Repo
.
get_by
(
Chat
,
id:
id
,
user_id:
user_id
),
%
User
{}
=
recipient
<-
User
.
get_cached_by_ap_id
(
chat
.
recipient
),
{
:ok
,
activity
}
<-
CommonAPI
.
post_chat_message
(
user
,
recipient
,
content
),
{
:ok
,
activity
}
<-
CommonAPI
.
post_chat_message
(
user
,
recipient
,
content
,
media_id:
params
[
:media_id
]),
message
<-
Object
.
normalize
(
activity
)
do
conn
|>
put_view
(
ChatMessageView
)
...
...
lib/pleroma/web/pleroma_api/views/chat_message_view.ex
View file @
20baa2ea
...
...
@@ -23,7 +23,10 @@ def render(
chat_id:
chat_id
|>
to_string
(),
account_id:
User
.
get_cached_by_ap_id
(
chat_message
[
"actor"
])
.
id
,
created_at:
Utils
.
to_masto_date
(
chat_message
[
"published"
]),
emojis:
StatusView
.
build_emojis
(
chat_message
[
"emoji"
])
emojis:
StatusView
.
build_emojis
(
chat_message
[
"emoji"
]),
attachment:
chat_message
[
"attachment"
]
&&
StatusView
.
render
(
"attachment.json"
,
attachment:
chat_message
[
"attachment"
])
}
end
...
...
test/web/activity_pub/object_validator_test.exs
View file @
20baa2ea
...
...
@@ -2,14 +2,41 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidatorTest do
use
Pleroma
.
DataCase
alias
Pleroma
.
Object
alias
Pleroma
.
Web
.
ActivityPub
.
ActivityPub
alias
Pleroma
.
Web
.
ActivityPub
.
Builder
alias
Pleroma
.
Web
.
ActivityPub
.
ObjectValidator
alias
Pleroma
.
Web
.
ActivityPub
.
ObjectValidators
.
LikeValidator
alias
Pleroma
.
Web
.
ActivityPub
.
ObjectValidators
.
AttachmentValidator
alias
Pleroma
.
Web
.
ActivityPub
.
Utils
alias
Pleroma
.
Web
.
CommonAPI
import
Pleroma
.
Factory
describe
"attachments"
do
test
"it turns mastodon attachments into our attachments"
do
attachment
=
%{
"url"
=>
"http://mastodon.example.org/system/media_attachments/files/000/000/002/original/334ce029e7bfb920.jpg"
,
"type"
=>
"Document"
,
"name"
=>
nil
,
"mediaType"
=>
"image/jpeg"
}
{
:ok
,
attachment
}
=
AttachmentValidator
.
cast_and_validate
(
attachment
)
|>
Ecto
.
Changeset
.
apply_action
(
:insert
)
assert
[
%{
href:
"http://mastodon.example.org/system/media_attachments/files/000/000/002/original/334ce029e7bfb920.jpg"
,
type:
"Link"
,
mediaType:
"image/jpeg"
}
]
=
attachment
.
url
end
end
describe
"chat message create activities"
do
test
"it is invalid if the object already exists"
do
user
=
insert
(
:user
)
...
...
@@ -52,7 +79,28 @@ test "it is invalid if the object data has a different `to` or `actor` field" do
test
"validates for a basic object we build"
,
%{
valid_chat_message:
valid_chat_message
}
do
assert
{
:ok
,
object
,
_meta
}
=
ObjectValidator
.
validate
(
valid_chat_message
,
[])
assert
object
==
valid_chat_message
assert
Map
.
put
(
valid_chat_message
,
"attachment"
,
nil
)
==
object
end
test
"validates for a basic object with an attachment"
,
%{
valid_chat_message:
valid_chat_message
,
user:
user
}
do
file
=
%
Plug
.
Upload
{
content_type:
"image/jpg"
,
path:
Path
.
absname
(
"test/fixtures/image.jpg"
),
filename:
"an_image.jpg"
}
{
:ok
,
attachment
}
=
ActivityPub
.
upload
(
file
,
actor:
user
.
ap_id
)
valid_chat_message
=
valid_chat_message
|>
Map
.
put
(
"attachment"
,
attachment
.
data
)
assert
{
:ok
,
object
,
_meta
}
=
ObjectValidator
.
validate
(
valid_chat_message
,
[])
assert
object
[
"attachment"
]
end
test
"does not validate if the message is longer than the remote_limit"
,
%{
...
...
test/web/activity_pub/object_validators/types/object_id_test.exs
View file @
20baa2ea
# Pleroma: A lightweight social networking server
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule
Pleroma
.
Web
.
ObjectValidators
.
Types
.
ObjectIDTest
do
alias
Pleroma
.
Web
.
ActivityPub
.
ObjectValidators
.
Types
.
ObjectID
use
Pleroma
.
DataCase
...
...
test/web/pleroma_api/controllers/chat_controller_test.exs
View file @
20baa2ea
...
...
@@ -6,6 +6,7 @@ defmodule Pleroma.Web.PleromaAPI.ChatControllerTest do
alias
Pleroma
.
Chat
alias
Pleroma
.
Web
.
CommonAPI
alias
Pleroma
.
Web
.
ActivityPub
.
ActivityPub
import
Pleroma
.
Factory
...
...
@@ -49,6 +50,32 @@ test "it posts a message to the chat", %{conn: conn, user: user} do
assert
result
[
"content"
]
==
"Hallo!!"
assert
result
[
"chat_id"
]
==
chat
.
id
|>
to_string
()
end
test
"it works with an attachment"
,
%{
conn:
conn
,
user:
user
}
do
file
=
%
Plug
.
Upload
{
content_type:
"image/jpg"
,
path:
Path
.
absname
(
"test/fixtures/image.jpg"
),
filename:
"an_image.jpg"
}
{
:ok
,
upload
}
=
ActivityPub
.
upload
(
file
,
actor:
user
.
ap_id
)
other_user
=
insert
(
:user
)
{
:ok
,
chat
}
=
Chat
.
get_or_create
(
user
.
id
,
other_user
.
ap_id
)
result
=
conn
|>
put_req_header
(
"content-type"
,
"application/json"
)
|>
post
(
"/api/v1/pleroma/chats/
#{
chat
.
id
}
/messages"
,
%{
"content"
=>
"Hallo!!"
,
"media_id"
=>
to_string
(
upload
.
id
)
})
|>
json_response_and_validate_schema
(
200
)
assert
result
[
"content"
]
==
"Hallo!!"
assert
result
[
"chat_id"
]
==
chat
.
id
|>
to_string
()
end
end
describe
"GET /api/v1/pleroma/chats/:id/messages"
do
...
...
test/web/pleroma_api/views/chat_message_view_test.exs
View file @
20baa2ea
...
...
@@ -9,12 +9,21 @@ defmodule Pleroma.Web.PleromaAPI.ChatMessageViewTest do
alias
Pleroma
.
Object
alias
Pleroma
.
Web
.
CommonAPI
alias
Pleroma
.
Web
.
PleromaAPI
.
ChatMessageView
alias
Pleroma
.
Web
.
ActivityPub
.
ActivityPub
import
Pleroma
.
Factory
test
"it displays a chat message"
do
user
=
insert
(
:user
)
recipient
=
insert
(
:user
)
file
=
%
Plug
.
Upload
{
content_type:
"image/jpg"
,
path:
Path
.
absname
(
"test/fixtures/image.jpg"
),
filename:
"an_image.jpg"
}
{
:ok
,
upload
}
=
ActivityPub
.
upload
(
file
,
actor:
user
.
ap_id
)
{
:ok
,
activity
}
=
CommonAPI
.
post_chat_message
(
user
,
recipient
,
"kippis :firefox:"
)
chat
=
Chat
.
get
(
user
.
id
,
recipient
.
ap_id
)
...
...
@@ -30,7 +39,7 @@ test "it displays a chat message" do
assert
chat_message
[
:created_at
]
assert
match?
([%{
shortcode:
"firefox"
}],
chat_message
[
:emojis
])
{
:ok
,
activity
}
=
CommonAPI
.
post_chat_message
(
recipient
,
user
,
"gkgkgk"
)
{
:ok
,
activity
}
=
CommonAPI
.
post_chat_message
(
recipient
,
user
,
"gkgkgk"
,
media_id:
upload
.
id
)
object
=
Object
.
normalize
(
activity
)
...
...
@@ -40,5 +49,6 @@ test "it displays a chat message" do
assert
chat_message_two
[
:content
]
==
"gkgkgk"
assert
chat_message_two
[
:account_id
]
==
recipient
.
id
assert
chat_message_two
[
:chat_id
]
==
chat_message
[
:chat_id
]
assert
chat_message_two
[
:attachment
]
end
end
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment