Я создаю простой чат, используя Vue, Pusher и Firebase - Используя каналы присутствия. Он работает идеально локально, но после развертывания в Firebase Pusher не работает.
Я использовал этот учебник в качестве отправной точки, для всех настроек et c: https://pusher.com/tutorials/game-vuejs
Развернутая версия находится здесь: https://quizgame-34be0.web.app/?id=y0yds1d3# / с console.log, чтобы увидеть, что происходит с объектом-толкачом. Канал, кажется, существует, но не добавляет новых участников.
Есть какие-нибудь идеи относительно того, как я могу правильно выполнить это развертывание?
Сервер. js
// server.js
const express = require('express')
const path = require('path')
const bodyParser = require('body-parser')
const app = express()
const Pusher = require('pusher')
const crypto = require('crypto')
require('dotenv').config()
//initialize Pusher with your appId, key and secret
const pusher = new Pusher({
appId: '*******',
key: '*******',
secret: '*******',
cluster: 'eu',
encrypted: true
})
// Body parser middleware
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: false }))
// The code below helps to fix any potential CORS issue.
app.use((req, res, next) => {
// Website you wish to allow to connect
res.setHeader('Access-Control-Allow-Origin', '*')
// Request methods you wish to allow
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE')
// Request headers you wish to allow
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type')
// Set to true if you need the website to include cookies in the requests sent
// to the API (e.g. in case you use sessions)
res.setHeader('Access-Control-Allow-Credentials', true)
// Pass to next layer of middleware
next()
})
// Index API route for the Express app
app.get('/', (req, res) => {
res.send('Welcome all')
})
// API route used by Pusher as a way of authenticating users
app.post('/pusher/auth', (req, res) => {
let socketId = req.body.socket_id
let channel = req.body.channel_name
// Generate a random string and use as presence channel user_id
let presenceData = {
user_id: crypto.randomBytes(16).toString('hex')
}
let auth = pusher.authenticate(socketId, channel, presenceData)
res.send(auth)
})
// Set port to be used by Node.js
app.set('port', (5000))
app.listen(app.get('port'), () => {
console.log('Node app is running on port', app.get('port'))
})
ChannelDetails. vue
<script>
import Pusher from 'pusher-js'
const pusher = new Pusher('********', {
cluster: 'eu',
encrypted: true,
authEndpoint: 'http://localhost:5000/pusher/auth'
})
export default ({
getPresenceID () {
// This function checks the address bar of the browser for params
let getQueryString = (field, url) => {
let href = url ? url : window.location.href
let reg = new RegExp('[?&]' + field + '=([^&#]*)', 'i')
let string = reg.exec(href)
return string ? string[1] : null
}
// Appends 'presence' to the result
let id = getQueryString('id')
id = 'presence-' + id
return id
},
subscribeToPusher () {
let presenceid = this.getPresenceID()
let channel = pusher.subscribe(presenceid)
return channel
}
})
</script>
Дом. vue
<template>
<div>
<div v-if="activeUser.name" class="home">
<div class="link-bar padding-1">
<h3>Invite friends to chat by sharing this link <a :href="url" target="blank">{{url}}</a></h3>
</div>
<div class="feed padding-1">
<h1 class="pb-1">Chat Feed</h1>
<div class="feed-messages" style="overflow-y: scroll; height:400px; position: relative; bottom:0;">
<div v-for="message in messages" :key="message">
<Message :message="message" :activeUser="activeUser.name"/>
</div>
</div>
<div class="feed-input">
<input type="text" ref="message" placeholder="Enter chat message"/>
<button v-on:click="sendMessage()">Send</button>
</div>
</div>
<div class="users padding-1">
<h1 class="pb-1">Users</h1>
<div class="users-me pb-1 mb-1">
<h2><User :user="activeUser"/></h2>
<h2 class="ml-2"> - you </h2>
</div>
<div class="users-other">
<div v-for="user in getOtherUsers" :key="user">
<h2><User :user="user"/></h2>
</div>
</div>
</div>
</div>
<div v-else class="home-wall">
<h1> Add username to enter chatroom</h1>
<div>
<input type="text" ref="input" placeholder="enter new username"/>
<button v-on:click="addName()">submit</button>
</div>
</div>
</div>
</template>
<script>
// Import ChannelDetails component created in diff file
import ChannelDetails from '@/components/ChannelDetails'
//components
import User from '@/components/User'
import Message from '@/components/Message'
export default {
name: 'home',
components: { User, Message },
data () {
return {
users: [],
messages: [],
activeUser: {
id: null,
name: null,
},
//channel id
presenceid: null,
//url for current channel
url: null
}
},
created () {
console.log('created entered')
this.fetchData()
},
computed: {
getOtherUsers() {
return this.users.filter((user) => {
return user.id != this.activeUser.id;
})
}
},
methods: {
fetchData () {
// Sets the data instance presenceid variable to the result of the getUniqueId function
this.presenceid = this.getUniqueId()
// This checks if there's no presence ID in the URL via the checkPresenceID function and appends the presenceid to the current URL so that we can have the URL end with a parameter
if (!this.checkPresenceID()) {
var separator = (window.location.href.indexOf('?') === -1) ? '?' : '&'
window.location.href = window.location.href + separator + this.presenceid
}
// Sets the data instance url variable to the current URL.
this.url = window.location.href
// The channel variable is set to to the subscribeToPusher function in ChannelDetails.
let channel = ChannelDetails.subscribeToPusher()
console.log(channel)
// SUBSCRIPTION SUCCEEDED: Triggered once a subscription has been made to a presence channel, exposing the members object to the new user
channel.bind('pusher:subscription_succeeded', members => {
console.log('sub succeed', members)
// add own id
this.activeUser.id = channel.members.me.id
// add the existing members
members.each((member) => {
//if it is the current user
this.users.push(this.createMember(member.id))
})
})
//MEMBER ADDED: Triggered when a new user joins. Exposes the new member object to all
channel.bind('pusher:member_added', newMember => {
console.log('sub added', newMember)
this.users.push(this.createMember(newMember.id))
//in return, user sends their username back
this.broadCastName()
})
// MEMBER REMOVED: When someone leaves the channel.
channel.bind('pusher:member_removed', member => {
this.users.forEach((user, index) => {
if (user.id === member.id) {
this.users.splice(index, 1)
this.sendAlert(user.name, 'has left the room')
}
})
})
// CLIENT SEND NEWUSER NAME: existing users recieve new name
channel.bind('client-send-name', (res) => {
this.users.forEach((user) => {
if (user.id === res.id) {
user.name = res.name
}
})
})
channel.bind('client-send-message', (res) => {
this.messages.push(res.message)
})
},
///////////////////// LOGIC FOR MEMBER MANAGEMENT /////////////////////
createMember(id) {
const memberObject = {}
memberObject.id = id
memberObject.name = ''
return memberObject
},
addName() {
//add it to the users object
this.users.forEach((user) => {
if (user.id === this.activeUser.id) {
user.name = this.$refs.input.value
}
})
//add it to personal details
this.activeUser.name = this.$refs.input.value
//broadcast new name with corresponding ID
let channel = ChannelDetails.subscribeToPusher()
channel.trigger('client-send-name', {id: this.activeUser.id, name: this.activeUser.name })
//clear fields
this.$refs.input.value = ""
//send activity alert to the channel
this.sendAlert(this.activeUser.name, 'joined the room')
},
broadCastName() {
let channel = ChannelDetails.subscribeToPusher()
channel.trigger('client-send-name', {id: this.activeUser.id, name: this.activeUser.name })
},
//// LOGIC FOR MESSAGE MANAGEMENT //////////////////////////////////
sendMessage() {
if (this.$refs.message.value) {
let channel = ChannelDetails.subscribeToPusher()
let newMessage = {}
newMessage.message = this.$refs.message.value
newMessage.author = this.activeUser.name
newMessage.authorId = this.activeUser.id
this.messages.push(newMessage)
channel.trigger('client-send-message', { message: newMessage})
this.$refs.message.value = ''
}
},
sendAlert(user, alert) {
let newMessage = {}
newMessage.message = user + ' has ' + alert
newMessage.author = "system"
newMessage.authorId = 0
let channel = ChannelDetails.subscribeToPusher()
channel.trigger('client-send-message', { message: newMessage})
},
//////// LOGIC FOR CHANNEL AND URL /////////////////////////////////
//generates random alphanumeric characters and adds a prefix of id= to the result.
getUniqueId () {
return 'id=' + Math.random().toString(36).substr(2, 8)
},
//This function checks the address bar of the browser for URL parameters
checkPresenceID () {
let getQueryString = (field, url) => {
let href = url ? url : window.location.href
let reg = new RegExp('[?&]' + field + '=([^&#]*)', 'i')
let string = reg.exec(href)
return string ? string[1] : null
}
let id = getQueryString('id')
return id
},
}
}
</script>