mirror of
https://github.com/h3poteto/whalebird-desktop
synced 2025-02-01 01:47:01 +01:00
refs #635 Connect to Pleroma with Web Socket to streaming update
This commit is contained in:
parent
c00fa89b4e
commit
d341c9205e
63
package-lock.json
generated
63
package-lock.json
generated
@ -208,6 +208,11 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.1.tgz",
|
||||
"integrity": "sha512-FhlMa34NHp9K5MY1Uz8yb+ZvuX0pnvn3jScRSNAb75KHGB8d3rEU6hqMs3Z2vjuytcMfRg6c5CHMc3wtYyD2/A=="
|
||||
},
|
||||
"@types/events": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/events/-/events-1.2.0.tgz",
|
||||
"integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA=="
|
||||
},
|
||||
"@types/form-data": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-2.2.1.tgz",
|
||||
@ -279,6 +284,15 @@
|
||||
"@types/uglify-js": "*"
|
||||
}
|
||||
},
|
||||
"@types/websocket": {
|
||||
"version": "0.0.40",
|
||||
"resolved": "https://registry.npmjs.org/@types/websocket/-/websocket-0.0.40.tgz",
|
||||
"integrity": "sha512-ldteZwWIgl9cOy7FyvYn+39Ah4+PfpVE72eYKw75iy2L0zTbhbcwvzeJ5IOu6DQP93bjfXq0NGHY6FYtmYoqFQ==",
|
||||
"requires": {
|
||||
"@types/events": "*",
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"abbrev": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
||||
@ -10479,16 +10493,18 @@
|
||||
"dev": true
|
||||
},
|
||||
"megalodon": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/megalodon/-/megalodon-0.3.0.tgz",
|
||||
"integrity": "sha512-PSSqnLmZUToMF6yFpufq58By0+Pc+ar8NiT+xrQlG6GW6O6CedWc2ZR1bQwUVO5pJjRnEvI4oyp1xA5Gu3hBAA==",
|
||||
"version": "0.4.2",
|
||||
"resolved": "https://registry.npmjs.org/megalodon/-/megalodon-0.4.2.tgz",
|
||||
"integrity": "sha512-k5xRgg2H+p8yEM9O9kdB6yMgxruHcZMFB5iS2F+u3N1hM4RcW8pF7H2Q0Pip8+7mlzGolLVxDu+W0atHnNAPcQ==",
|
||||
"requires": {
|
||||
"@types/oauth": "^0.9.0",
|
||||
"@types/request": "^2.47.0",
|
||||
"@types/websocket": "0.0.40",
|
||||
"axios": "^0.18.0",
|
||||
"oauth": "^0.9.15",
|
||||
"request": "^2.87.0",
|
||||
"typescript": "^2.9.1"
|
||||
"typescript": "^2.9.1",
|
||||
"websocket": "^1.0.28"
|
||||
}
|
||||
},
|
||||
"mem": {
|
||||
@ -16375,6 +16391,14 @@
|
||||
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
|
||||
"dev": true
|
||||
},
|
||||
"typedarray-to-buffer": {
|
||||
"version": "3.1.5",
|
||||
"resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
|
||||
"integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
|
||||
"requires": {
|
||||
"is-typedarray": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"typescript": {
|
||||
"version": "2.9.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz",
|
||||
@ -17764,6 +17788,32 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"websocket": {
|
||||
"version": "1.0.28",
|
||||
"resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.28.tgz",
|
||||
"integrity": "sha512-00y/20/80P7H4bCYkzuuvvfDvh+dgtXi5kzDf3UcZwN6boTYaKvsrtZ5lIYm1Gsg48siMErd9M4zjSYfYFHTrA==",
|
||||
"requires": {
|
||||
"debug": "^2.2.0",
|
||||
"nan": "^2.11.0",
|
||||
"typedarray-to-buffer": "^3.1.5",
|
||||
"yaeti": "^0.0.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"nan": {
|
||||
"version": "2.11.1",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.11.1.tgz",
|
||||
"integrity": "sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"websocket-driver": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz",
|
||||
@ -18017,6 +18067,11 @@
|
||||
"integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
|
||||
"dev": true
|
||||
},
|
||||
"yaeti": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz",
|
||||
"integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc="
|
||||
},
|
||||
"yallist": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
|
||||
|
@ -110,7 +110,7 @@
|
||||
"i18next-sync-fs-backend": "^1.1.0",
|
||||
"is-empty": "^1.2.0",
|
||||
"lodash": "^4.17.10",
|
||||
"megalodon": "^0.3.0",
|
||||
"megalodon": "0.4.2",
|
||||
"moment": "^2.21.0",
|
||||
"mousetrap": "^1.6.2",
|
||||
"nedb": "^1.8.0",
|
||||
|
@ -13,7 +13,7 @@ import openAboutWindow from 'about-window'
|
||||
|
||||
import Authentication from './auth'
|
||||
import Account from './account'
|
||||
import Streaming from './streaming'
|
||||
import StreamingManager from './streaming_manager'
|
||||
import Preferences from './preferences'
|
||||
import Fonts from './fonts'
|
||||
import Hashtags from './hashtags'
|
||||
@ -396,8 +396,8 @@ ipcMain.on('start-user-streaming', (event, ac) => {
|
||||
userStreaming = null
|
||||
}
|
||||
|
||||
userStreaming = new Streaming(account)
|
||||
userStreaming.startUserStreaming(
|
||||
userStreaming = new StreamingManager(account)
|
||||
userStreaming.startUser(
|
||||
(update) => {
|
||||
event.sender.send('update-start-user-streaming', update)
|
||||
},
|
||||
@ -438,9 +438,9 @@ ipcMain.on('start-local-streaming', (event, ac) => {
|
||||
localStreaming = null
|
||||
}
|
||||
|
||||
localStreaming = new Streaming(account)
|
||||
localStreaming = new StreamingManager(account)
|
||||
localStreaming.start(
|
||||
'/streaming/public/local',
|
||||
'public/local',
|
||||
(update) => {
|
||||
event.sender.send('update-start-local-streaming', update)
|
||||
},
|
||||
@ -475,9 +475,9 @@ ipcMain.on('start-public-streaming', (event, ac) => {
|
||||
publicStreaming = null
|
||||
}
|
||||
|
||||
publicStreaming = new Streaming(account)
|
||||
publicStreaming = new StreamingManager(account)
|
||||
publicStreaming.start(
|
||||
'/streaming/public',
|
||||
'public',
|
||||
(update) => {
|
||||
event.sender.send('update-start-public-streaming', update)
|
||||
},
|
||||
@ -512,9 +512,9 @@ ipcMain.on('start-list-streaming', (event, obj) => {
|
||||
listStreaming = null
|
||||
}
|
||||
|
||||
listStreaming = new Streaming(account)
|
||||
listStreaming = new StreamingManager(account)
|
||||
listStreaming.start(
|
||||
`/streaming/list?list=${obj.list_id}`,
|
||||
`list?list=${obj.list_id}`,
|
||||
(update) => {
|
||||
event.sender.send('update-start-list-streaming', update)
|
||||
},
|
||||
@ -549,9 +549,9 @@ ipcMain.on('start-tag-streaming', (event, obj) => {
|
||||
tagStreaming = null
|
||||
}
|
||||
|
||||
tagStreaming = new Streaming(account)
|
||||
tagStreaming = new StreamingManager(account)
|
||||
tagStreaming.start(
|
||||
`/streaming/hashtag?tag=${obj.tag}`,
|
||||
`hashtag?tag=${obj.tag}`,
|
||||
(update) => {
|
||||
event.sender.send('update-start-tag-streaming', update)
|
||||
},
|
||||
|
@ -13,7 +13,10 @@ export default class Streaming {
|
||||
|
||||
startUserStreaming (updateCallback, notificationCallback, errCallback) {
|
||||
this.listener = this.client.stream('/streaming/user')
|
||||
log.info('/streaming/user started')
|
||||
|
||||
this.listener.on('connect', _ => {
|
||||
log.info('/streaming/user started')
|
||||
})
|
||||
|
||||
this.listener.on('update', (status) => {
|
||||
updateCallback(status)
|
||||
@ -26,11 +29,17 @@ export default class Streaming {
|
||||
this.listener.on('error', (err) => {
|
||||
errCallback(err)
|
||||
})
|
||||
|
||||
this.listener.on('connection-limit-exceeded', err => {
|
||||
errCallback(err)
|
||||
})
|
||||
}
|
||||
|
||||
start (path, updateCallback, errCallback) {
|
||||
this.listener = this.client.stream(path)
|
||||
log.info(`${path} started`)
|
||||
this.listener.on('connect', _ => {
|
||||
log.info(`${path} started`)
|
||||
})
|
||||
|
||||
this.listener.on('update', (status) => {
|
||||
updateCallback(status)
|
||||
@ -39,10 +48,16 @@ export default class Streaming {
|
||||
this.listener.on('error', (err) => {
|
||||
errCallback(err)
|
||||
})
|
||||
|
||||
this.listener.on('connection-limit-exceeded', err => {
|
||||
errCallback(err)
|
||||
})
|
||||
}
|
||||
|
||||
stop () {
|
||||
this.listener.stop()
|
||||
log.info('streaming stopped')
|
||||
if (this.listener) {
|
||||
this.listener.stop()
|
||||
log.info('streaming stopped')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
96
src/main/streaming_manager.js
Normal file
96
src/main/streaming_manager.js
Normal file
@ -0,0 +1,96 @@
|
||||
import Mastodon from 'megalodon'
|
||||
import Streaming from './streaming'
|
||||
import WebSocket from './websocket'
|
||||
import log from 'electron-log'
|
||||
|
||||
export default class StreamingManager {
|
||||
constructor (account) {
|
||||
this.account = account
|
||||
this.streaming = new Streaming(account)
|
||||
this.websocket = new WebSocket(account)
|
||||
this.mastodon = true
|
||||
}
|
||||
|
||||
/**
|
||||
* Find Pleroma comment in the response
|
||||
*/
|
||||
async detectPleroma () {
|
||||
const data = await Mastodon.get('/instance', {}, this.account.baseURL + '/api/v1')
|
||||
if (data.version.includes('Pleroma')) {
|
||||
this.mastodon = false
|
||||
log.info('detect Pleroma')
|
||||
}
|
||||
}
|
||||
|
||||
startUser (updateCallback, notificationCallback, errCallback) {
|
||||
this.detectPleroma()
|
||||
.then(() => {
|
||||
if (this.mastodon) {
|
||||
this._startUserStreaming(updateCallback, notificationCallback, errCallback)
|
||||
} else {
|
||||
this._startUserSocket(updateCallback, notificationCallback, errCallback)
|
||||
}
|
||||
})
|
||||
.catch(err => errCallback(err))
|
||||
}
|
||||
|
||||
start (path, updateCallback, errCallback) {
|
||||
this.detectPleroma()
|
||||
.then(() => {
|
||||
if (this.mastodon) {
|
||||
this._startStreaming(path, updateCallback, errCallback)
|
||||
} else {
|
||||
this._startSocket(path, updateCallback, errCallback)
|
||||
}
|
||||
})
|
||||
.catch(err => errCallback(err))
|
||||
}
|
||||
|
||||
stop () {
|
||||
this._stopStreaming()
|
||||
this._stopSocket()
|
||||
}
|
||||
|
||||
/**
|
||||
* Using streaming for Mastodon
|
||||
*/
|
||||
_startUserStreaming (updateCallback, notificationCallback, errCallback) {
|
||||
this.streaming.startUserStreaming(updateCallback, notificationCallback, errCallback)
|
||||
}
|
||||
|
||||
_startStreaming (path, updateCallback, errCallback) {
|
||||
const target = `/streaming/${path}`
|
||||
this.streaming.start(
|
||||
target,
|
||||
updateCallback,
|
||||
errCallback
|
||||
)
|
||||
}
|
||||
|
||||
_stopStreaming () {
|
||||
this.streaming.stop()
|
||||
}
|
||||
|
||||
/**
|
||||
* Using websocket for Pleroma
|
||||
*/
|
||||
_startUserSocket (updateCallback, notificationCallback, errCallback) {
|
||||
this.websocket.startUserStreaming(updateCallback, notificationCallback, errCallback)
|
||||
}
|
||||
|
||||
_startSocket (path, updateCallback, errCallback) {
|
||||
let stream = path
|
||||
if (stream === 'public/local') {
|
||||
stream = 'public:local'
|
||||
}
|
||||
this.websocket.start(
|
||||
stream,
|
||||
updateCallback,
|
||||
errCallback
|
||||
)
|
||||
}
|
||||
|
||||
_stopSocket () {
|
||||
this.websocket.stop()
|
||||
}
|
||||
}
|
73
src/main/websocket.js
Normal file
73
src/main/websocket.js
Normal file
@ -0,0 +1,73 @@
|
||||
import Mastodon from 'megalodon'
|
||||
import log from 'electron-log'
|
||||
|
||||
export default class WebSocket {
|
||||
constructor (account) {
|
||||
this.account = account
|
||||
this.client = new Mastodon(
|
||||
account.accessToken,
|
||||
account.baseURL + '/api/v1'
|
||||
)
|
||||
this.listener = null
|
||||
}
|
||||
|
||||
startUserStreaming (updateCallback, notificationCallback, errCallback) {
|
||||
this.listener = this.client.socket('/streaming', 'user')
|
||||
|
||||
this.listener.on('connect', _ => {
|
||||
log.info('/streaming/?stream=user started')
|
||||
})
|
||||
|
||||
this.listener.on('update', (status) => {
|
||||
updateCallback(status)
|
||||
})
|
||||
|
||||
this.listener.on('notification', (notification) => {
|
||||
notificationCallback(notification)
|
||||
})
|
||||
|
||||
this.listener.on('error', (err) => {
|
||||
errCallback(err)
|
||||
})
|
||||
|
||||
this.listener.on('parser-error', (err) => {
|
||||
errCallback(err)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Start new custom streaming with websocket.
|
||||
* @param stream Path of streaming.
|
||||
* @param updateCallback A callback function which is called update.
|
||||
* @param errCallback A callback function which ic called error.
|
||||
* When local timeline, the path is `public:local`.
|
||||
* When public timeline, the path is `public`.
|
||||
* When hashtag timeline, the path is `hashtag&tag=tag_name`.
|
||||
* When list timeline, the path is `list&list=list_id`.
|
||||
*/
|
||||
start (stream, updateCallback, errCallback) {
|
||||
this.listener = this.client.socket('/streaming', stream)
|
||||
this.listener.on('connect', _ => {
|
||||
log.info(`/streaming/?stream=${stream} started`)
|
||||
})
|
||||
|
||||
this.listener.on('update', status => {
|
||||
updateCallback(status)
|
||||
})
|
||||
|
||||
this.listener.on('error', (err) => {
|
||||
errCallback(err)
|
||||
})
|
||||
|
||||
this.listener.on('parser-error', (err) => {
|
||||
errCallback(err)
|
||||
})
|
||||
}
|
||||
|
||||
stop () {
|
||||
if (this.listener) {
|
||||
this.listener.stop()
|
||||
log.info('streaming stopped')
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user