Mastodon: websocket token and card
This commit is contained in:
parent
74935ced6c
commit
a97ffb491b
12
package.json
12
package.json
|
@ -21,12 +21,6 @@
|
|||
"@vue/cli-plugin-typescript": "^3.0.3",
|
||||
"@vue/cli-service": "^3.0.3",
|
||||
"babel-plugin-transform-decorators": "^6.24.1",
|
||||
"pug": "^2.0.3",
|
||||
"pug-plain-loader": "^1.0.0",
|
||||
"sass-loader": "^7.0.1",
|
||||
"tslint-config-prettier": "^1.15.0",
|
||||
"tslint-plugin-prettier": "^1.3.0",
|
||||
"typescript": "^3.0.0",
|
||||
"core-js": "^2.6.5",
|
||||
"css-loader": "^0.28.11",
|
||||
"eslint": "^5.16.0",
|
||||
|
@ -37,6 +31,12 @@
|
|||
"less-loader": "^4.1.0",
|
||||
"node-sass": "^4.11.0",
|
||||
"optimize-css-assets-webpack-plugin": "^4.0.0",
|
||||
"pug": "^2.0.3",
|
||||
"pug-plain-loader": "^1.0.0",
|
||||
"sass-loader": "^7.0.1",
|
||||
"tslint-config-prettier": "^1.15.0",
|
||||
"tslint-plugin-prettier": "^1.3.0",
|
||||
"typescript": "^3.0.0",
|
||||
"url-loader": "^1.0.1",
|
||||
"vue-loader": "^15.4.2",
|
||||
"vue-style-loader": "^4.1.2",
|
||||
|
|
|
@ -24,7 +24,7 @@ import ServiceClient from '@/components/ServiceClient'
|
|||
import Lists from '@/helpers/lists/Lists'
|
||||
import AxiosLodable from '@/helpers/loadable/AxiosLoadable'
|
||||
import AxiosLodableMore from '@/helpers/loadable/AxiosLoadableMore'
|
||||
import { AUTH, getRest } from './Mastodon.vue'
|
||||
import { AUTH, getHeaders, getRest } from './Mastodon.vue'
|
||||
import Notification from './Notification.vue'
|
||||
import Status from './Status.vue'
|
||||
import { MarkMessage, Notification as INotification, Options, Status as IStatus } from './Types'
|
||||
|
@ -98,36 +98,40 @@ export default class Client extends Mixins<ServiceClient<Options>>(ServiceClient
|
|||
}
|
||||
|
||||
setupStream() {
|
||||
const ws = new WebSocket(
|
||||
`wss://${this.auth.get(AUTH.SERVER)}/api/v1/streaming?access_token=${this.auth.get(AUTH.TOKEN)}&stream=user`
|
||||
)
|
||||
ws.onmessage = event => {
|
||||
const data = JSON.parse(event.data)
|
||||
const payload = JSON.parse(data.payload)
|
||||
switch (data.event) {
|
||||
case 'update':
|
||||
this.statues.with(s => s.unshift(payload))
|
||||
break
|
||||
|
||||
case 'notification':
|
||||
this.notifications.with(n => n.unshift(payload))
|
||||
break
|
||||
|
||||
case 'delete':
|
||||
this.statues.with(st => Lists.removeFirstBy(st, s => s.id, payload.id))
|
||||
break
|
||||
}
|
||||
}
|
||||
ws.onerror = ev => this.emitError(ev.type)
|
||||
ws.onclose = () => {
|
||||
this.emitError(
|
||||
'Mastodon stream disconnected !' +
|
||||
(this.options.reconnect ? ' Reconnecting...' : '')
|
||||
this.get('/instance').then(res => {
|
||||
const oldAuth = res.data.version < '2.8.4' ? `access_token=${this.auth.get(AUTH.TOKEN)}&` : ''
|
||||
const ws = new WebSocket(
|
||||
`wss://${this.auth.get(AUTH.SERVER)}/api/v1/streaming?${oldAuth}stream=user`,
|
||||
this.auth.get(AUTH.TOKEN)
|
||||
)
|
||||
if (this.options.reconnect) {
|
||||
setTimeout(() => this.setupStream(), this.options.timeout)
|
||||
ws.onmessage = event => {
|
||||
const data = JSON.parse(event.data)
|
||||
const payload = JSON.parse(data.payload)
|
||||
switch (data.event) {
|
||||
case 'update':
|
||||
this.statues.with(s => s.unshift(payload))
|
||||
break
|
||||
|
||||
case 'notification':
|
||||
this.notifications.with(n => n.unshift(payload))
|
||||
break
|
||||
|
||||
case 'delete':
|
||||
this.statues.with(st => Lists.removeFirstBy(st, s => s.id, payload.id))
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
ws.onerror = ev => this.emitError(ev.type)
|
||||
ws.onclose = () => {
|
||||
this.emitError(
|
||||
'Mastodon stream disconnected !' +
|
||||
(this.options.reconnect ? ' Reconnecting...' : '')
|
||||
)
|
||||
if (this.options.reconnect) {
|
||||
setTimeout(() => this.setupStream(), this.options.timeout)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -191,6 +195,12 @@ export default class Client extends Mixins<ServiceClient<Options>>(ServiceClient
|
|||
background-color: #00000044
|
||||
color: white
|
||||
padding: .5em
|
||||
.card
|
||||
@include tile
|
||||
padding: .2em
|
||||
display: block
|
||||
.provider
|
||||
float: right
|
||||
.meta
|
||||
margin-left: 1em + $avatarSize
|
||||
font-size: .8em
|
||||
|
|
|
@ -38,10 +38,13 @@ import { ParseEmojisMixin } from './ParseEmojisMixin'
|
|||
import { Account, Options } from './Types'
|
||||
|
||||
export const AUTH = { SERVER: 'server', TOKEN: 'token' }
|
||||
export function getHeaders(auth: Auth) {
|
||||
return { headers: { Authorization: 'Bearer ' + auth.get(AUTH.TOKEN) } }
|
||||
}
|
||||
export function getRest(auth: Auth, timeout: number) {
|
||||
return axios.create({
|
||||
baseURL: `https://${auth.get(AUTH.SERVER)}/api/v1/`, timeout,
|
||||
headers: { Authorization: 'Bearer ' + auth.get(AUTH.TOKEN) },
|
||||
...getHeaders(auth)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,15 @@
|
|||
img(v-if="media.type == 'image' || media.type == 'gifv'" :src="media.preview_url" :alt="media.description" :title="media.description")
|
||||
template(v-else) Wrong type
|
||||
.gif(v-if="media.type == 'gifv'") GIF
|
||||
template(v-else) Hidden media
|
||||
template(v-else) Hidden media {{ media.description }}
|
||||
.poll(v-if="status.poll") {{ renderPoll(status.poll) }}
|
||||
a.card(v-if="status.card" :href="status.card.url" target="_blank")
|
||||
a.provider(v-if="status.card.provider_name" :src="status.card.provider_url" target="_blank") {{ status.card.provider_name }}
|
||||
.title {{ status.card.title }}
|
||||
.descr {{ status.card.description }}
|
||||
template(v-if="status.card.image")
|
||||
img(v-if="showMedia" :src="status.card.image")
|
||||
a(v-else-if="status.card.type == 'photo'" :src="status.card.image" target="_blank") Hidden media
|
||||
status.reblog(v-else :status="status.reblog" :showMedia="showMedia")
|
||||
|
||||
.meta(v-if="!status.reblog")
|
||||
|
@ -41,7 +49,7 @@ import FromNowMixin from '@/components/FromNowMixin'
|
|||
import ShowMediaMixin from '@/components/ShowMediaMixin'
|
||||
import Account from './Account.vue'
|
||||
import { ParseEmojisMixin } from './ParseEmojisMixin'
|
||||
import { MarkMessage, Status as IStatus } from './Types'
|
||||
import { Card, MarkMessage, Poll, Status as IStatus } from './Types'
|
||||
|
||||
@Component({ components: { Account } })
|
||||
export default class Status extends Mixins(ParseEmojisMixin, ShowMediaMixin, FromNowMixin) {
|
||||
|
@ -60,6 +68,10 @@ export default class Status extends Mixins(ParseEmojisMixin, ShowMediaMixin, Fro
|
|||
throw status.id // TODO:
|
||||
}
|
||||
|
||||
renderPoll(poll: Poll) {
|
||||
throw poll // TODO:
|
||||
}
|
||||
|
||||
@Emit('mark')
|
||||
emitMark(status: IStatus, action: 'reblog' | 'favourite', callback: CallableFunction, undo = false): MarkMessage {
|
||||
return {
|
||||
|
|
|
@ -34,7 +34,36 @@ export interface Status {
|
|||
replies_count: number
|
||||
in_reply_to_id?: number
|
||||
reblog?: Status
|
||||
spoiler_text?: string
|
||||
spoiler_text?: string,
|
||||
card?: Card,
|
||||
poll?: Poll
|
||||
}
|
||||
|
||||
export type CardType = 'link' | 'photo' | 'video' | 'rich'
|
||||
export interface Card {
|
||||
url: string
|
||||
title: string
|
||||
description: string
|
||||
image?: string
|
||||
type: CardType
|
||||
author_name?: string
|
||||
author_url?: string
|
||||
provider_name?: string
|
||||
provider_url?: string
|
||||
}
|
||||
|
||||
export interface PollOption {
|
||||
title: string
|
||||
votes_count?: number
|
||||
}
|
||||
export interface Poll {
|
||||
id: string
|
||||
expires_at?: string
|
||||
expired: boolean
|
||||
multiple: boolean
|
||||
votes_count: number
|
||||
options: PollOption[]
|
||||
voted?: boolean
|
||||
}
|
||||
|
||||
export interface Media {
|
||||
|
|
Loading…
Reference in New Issue