[Mattermost Integrations] Matterpoll Plugin (Webapp)

19103 단어 Mattermosttech
Mattermost 기사 요약: https://blog.kaakaa.dev/tags/mattermost/

본 보도에 관하여


Mattermost의 통합 기능 추가 달력 23일째 보도다.
이전부터 개발참가Matterpoll는 매터모스트 공식 플러그인 마켓플레이스에서 Community Plugin으로 공개됐다.
어제 기사에서는 Matterpoll Plugin의 서버 측 설치를 소개했고, 오늘 기사에서는 Matterpoll Plugin의 Webapp 측 기능을 소개했다.

Webapp 처리


위앱에서는 투표에 대한 사용자 개개인의 시각을 바꾸기 위한 처리가 이뤄졌다.

독립 포스트타입 투표 완료 답변 포인트


matterpoll-posttype.dio.png
Mattermos에 투고한 정보는 Mattermost에 Post 구조체의 데이터로 처리됩니다.그리고 Post 구조체Type 필드의 값에 따라 발언의 종류를 판별한다.기본적으로 Post.Type는 크게 두 가지 유형으로 나뉘는데 하나는 일반 사용자가 발표하는 메시지Post.Type가 빈 문자POST_DEFAULT이다.또 하나는 시스템이 채널 등에 참여할 때 발표한 소식Post.Typesystem_ 개시하다이다.
2 つのPost.Typeの投稿
Mattermost의 정보의 외관은 Message Attachements의 기능을 사용하여 어느 정도 변경할 수 있지만 Message Attachments에서는 모든Mattermost 사용자에게 같은 외관만 제공할 수 있으며 사용자마다 일부 정보를 변경하려면 플러그인으로 처리해야 한다.매터폴의 경우 자신이 투표한 답변이 어떤 것인지 보여주고 싶다는 요구가 있어 이 부분을 플러그인으로 처리했다.
플러그인을 통해 투고의 외관을 바꾸려면 먼저 서버 측에서 투고를 제작할 때 자신의 것을 설정해야 한다Post.Type.매터폴에서는 사선지령/poll을 실시했을 때 투표용 투고Post를 만들었고, 그때Post.Typecustom_matterpoll의 값을 설정했다.
server/plugin/plugin.go
...
const (
  ...
	// MatterpollPostType is post_type of posts generated by Matterpoll
	MatterpollPostType = "custom_matterpoll"
)
...
https://github.com/matterpoll/matterpoll/blob/45f095875a98fb1d4f3f166851c86f41b987493e/server/plugin/plugin.go#L53
server/plugin/command.go
...
  post := &model.Post{
		UserId:    p.botUserID,
		ChannelId: args.ChannelId,
		RootId:    args.RootId,
		Type:      MatterpollPostType,
		Props: map[string]interface{}{
			"poll_id": newPoll.ID,
		},
	}
	model.ParseSlackAttachment(post, actions)

	rPost, appErr := p.API.CreatePost(post)
...
https://github.com/matterpoll/matterpoll/blob/45f095875a98fb1d4f3f166851c86f41b987493e/server/plugin/command.go#L191
위에서 말한 바와 같이 Post.Type에는 플러그인만의 값을 설정하였으나 위앱 측에서 추가 처리custom_matterpollPost.Type하지 않으면 통상적인 발언과 같은 값으로 표시된다.Mattermost 플러그인은 WebApp 플러그인 APIregisterPostTypeComponent를 사용하여 설정Post.Type 시 재현 방법을 지정합니다.
registerPostTypeComponent 첫 번째 매개변수에 custom_matterpoll 문자열을 지정하고 두 번째 매개변수에 React 어셈블리를 지정합니다.Matterpoll의 경우 서버 측면Post.TypePost.Type이 지정되어 있기 때문에 다음과 같이 첫 번째 파라미터custom_matterpoll를 지정하고 두 번째 파라미터에 단독 React 구성 요소를 지정하여 호출registerPostTypeComponent합니다.
webapp/src/actions/config.js
import PostType from 'components/post_type';
...

    if (data.experimentalui) {
        registeredComponentId = registry.registerPostTypeComponent('custom_matterpoll', PostType);
    } else {
       registry.unregisterPostTypeComponent(registeredComponentId);
       registeredComponentId = '';
    }
...
https://github.com/matterpoll/matterpoll/blob/fa1f3aa8489deb24706937beac7d9976b0528ed7/webapp/src/actions/config.js#L11
registerPostTypeComponent 반환값으로 등록된 React 구성 요소에 대응하는 ID 문자열을 되돌려줍니다. 이것은 unregisterPostTypeComponent 등록을 해제할 때 필요한 것이기 때문에state에 저장합니다.
Matterpoll에서 Webapp 측의 기능은 Experimental 기능으로 설정에서 On/Off를 전환할 수 있기 때문에 설정을 변경하여 로그인/해제할 수 있습니다.
따라서 발언 외관 플러그인을 바꾸려면 React 구성 요소를 만들어야 합니다.이때 매터모스트 호스트가 구축한 발언과 관련한 DOM의 일부 표시는 변경할 수 있으면 좋겠지만 매터모스트의 리액트 구성 요소는 외부에서 참조할 수 있는 형태로 공개되지 않아 처음부터 직접 만들어야 해 매우 어렵다고 설명했다.다만, React 구성 요소를 개발할 때 몇 개의 유틸리티 함수를 사용할 수 있기 때문에 이 일대를 사용했다.
https://developers.mattermost.com/extend/plugins/webapp/reference/#post-utils

플러그인 전용 WebSocket 이벤트


matterpoll-ws.dio.png
Mattermost의 Server와 Webapp 간에는 WebSocket이 있습니다.
Webapp의 경우 웹소켓 이벤트를 등록할 때 독립적으로 처리하는 것이 registerWebSocketEventHandler 방법이다.이 방법은 웹소켓 이벤트 이름과 두 번째 파라미터에서 웹소켓 이벤트를 받을 때 실행되는 처리를 함수로 첫 번째 파라미터에 등록합니다.
Mattermost 기본 Pubblish의 WebSocket 이벤트는 API 문서 일람에 요약되어 메시지의 투고/삭제/편집과 채널의 제작/삭제, 참여/종료 등 사용자가 조작하는 이벤트를 포함한다.또 서버 측으로부터 각 플러그인에 대해 독자적인 웹소켓 이벤트를 진행할 수 있는 퍼블릭스, 매터폴에서 매터폴 플러그인의 설정이 변경되었을 때, 사용자가 투표에 대답할 때 자신의 웹소켓 이벤트를 보낼 수 있다.
플러그인만의 WebSocket 이벤트 Publith를 진행하려면 서버 측에서 플러그인 APIPublishWebSocketEvent를 실행하면 됩니다. Matterpoll은 투표 데이터가 변경될 때 이 처리를 호출하여 투표와 관련된 최신 데이터를 Webapp에 전송합니다.
server/plugin/api.go
func (p *MatterpollPlugin) publishPollMetadata(poll *poll.Poll, userID string) {
	hasAdminPermission, appErr := p.HasAdminPermission(poll, userID)
	if appErr != nil {
		p.API.LogWarn("Failed to check admin permission", "userID", userID, "pollID", poll.ID, "error", appErr.Error())
		hasAdminPermission = false
	}
	metadata := poll.GetMetadata(userID, hasAdminPermission)
	p.API.PublishWebSocketEvent("has_voted", metadata.ToMap(), &model.WebsocketBroadcast{UserId: userID})
}
https://github.com/matterpoll/matterpoll/blob/45f095875a98fb1d4f3f166851c86f41b987493e/server/plugin/api.go#L411
플러그인 APIPublishWebSocketEvent에는 세 개의 매개변수가 있으며 첫 번째 매개변수 Publish의 WebSocket 이벤트에 사용할 이벤트 이름을 지정합니다.실제로 여기에 지정된 활동명의 시작 부분custom_matterpoll을 활동명으로 바꿔치기 때문에 첫 번째 매개변수를'has voted'로 한 이번 예에서는 웹소켓 활동명custom_<pluginid>_으로 변경됐다.이벤트 이름에는 플러그 인 ID가 포함되어 있으므로 플러그 인 간의 이벤트 이름 충돌을 고려할 필요가 없습니다.
두 번째 매개변수에서 Publish할 데이터를 지정합니다.custom_com.github.matterpoll.matterpoll_has_voted 형식의value는 map 형식을 지정할 수 있지만 이 값은 Go의 원시 형식이나 mattermost-server/model 형식만 지정할 수 있습니다.다른 값을 지정하면 실행 중 인코딩 오류가 발생합니다.(Mattermost 서버의 로그를 확인하지 않으면 모르기 때문에 쉽게 빠져들 수 있습니다.)
세 번째 파라미터는 이 웹소켓 이벤트를 어떤 사용자에게 보낼지 결정합니다.model.WebsocketBroadcast의 정의를 보면 사용자 단위 이외에도 채널과 팀 단위로 지정할 수 있다(시도한 적은 없지만).
다음은 Webapp 측에서 서버 측 Publith의 WebSocket 이벤트interface{}를 처리하기 위해 위registerWebSocketEventHandler를 실행합니다.
webapp/src/plugin.jsx
export default class MatterPollPlugin {
    async initialize(registry, store) {
        ...
        registry.registerWebSocketEventHandler(
            'custom_' + pluginId + '_has_voted',
            (message) => {
                store.dispatch(websocketHasVoted(message.data));
            },
        );
        ...
    }
https://github.com/matterpoll/matterpoll/blob/0b797025cfbf319c43464fcf457d4cdfe5086188/webapp/src/plugin.jsx#L17
위에서 말한 바와 같이 웹소켓을 시작할 때 웹소켓을 받을 때의Handler에 로그인함으로써 Mattermost의 조작에 따라 웹소켓의 디스플레이 등을 변경할 수 있다.

최후


오늘은 Matterpoll Plugin이 Mattermost에서 투표를 할 수 있는 Webapp 측의 실시를 소개했다.
내일은 Matterpoll Plugin 개발 중인 테스트와 CI를 소개합니다.

좋은 웹페이지 즐겨찾기