Add shop-chat push notifications and a "send shop to users" endpoint
- shop-chat messages (buyer <-> shop owner) never sent any push notification at all — sendShopChatPushNotification (chatHelpers.js) now fires on every send, mirroring the existing regular-chat push path; data payload carries shop_id/buyer_id/sender_role so clients can route directly to the thread - New POST /shops/:id/send, mirroring the existing shop-product send endpoint — lets a user share a shop itself (not just one product) into a regular chat message as a sharedShop payload Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -7,6 +7,7 @@ const ShopModel = require('../../../models/ShopModel')
|
||||
const ShopChatMessageModel = require('../../../models/ShopChatMessageModel')
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const { optimizeImageFile } = require('../../../utils/imageOptimize')
|
||||
const { sendShopChatPushNotification } = require('../../../helpers/chatHelpers')
|
||||
let optimizeVideoFaststart = async () => {}
|
||||
try {
|
||||
({ optimizeVideoFaststart } = require('../../../utils/postVideoProcessing'))
|
||||
@@ -200,16 +201,27 @@ const sendShopChatMessage = async (req, res, next) => {
|
||||
const { content } = req.body
|
||||
if (!content || !content.trim()) return chatError(res, 422, 'متن پیام الزامی است')
|
||||
|
||||
const senderRole = isOwner ? 'shop' : 'buyer'
|
||||
const message = await ShopChatMessageModel.create({
|
||||
shop: shop._id,
|
||||
buyer: buyerId,
|
||||
senderRole: isOwner ? 'shop' : 'buyer',
|
||||
senderRole,
|
||||
senderId: req.user._id,
|
||||
content: content.trim(),
|
||||
readByShop: isOwner,
|
||||
readByBuyer: !isOwner
|
||||
})
|
||||
|
||||
sendShopChatPushNotification({
|
||||
shop,
|
||||
senderId: req.user._id,
|
||||
senderRole,
|
||||
buyerId,
|
||||
receiverId: isOwner ? buyerId : shop.owner
|
||||
}).catch((err) => {
|
||||
console.error('[shopChatController] push notification failed:', err.message)
|
||||
})
|
||||
|
||||
return res.status(201).json({ message })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
@@ -251,10 +263,11 @@ const sendShopChatFileMessage = async (req, res, next) => {
|
||||
}
|
||||
const fileUrl = `/shop-chat/${uniqueFileName}`
|
||||
|
||||
const senderRole = isOwner ? 'shop' : 'buyer'
|
||||
const message = await ShopChatMessageModel.create({
|
||||
shop: shop._id,
|
||||
buyer: buyerId,
|
||||
senderRole: isOwner ? 'shop' : 'buyer',
|
||||
senderRole,
|
||||
senderId: req.user._id,
|
||||
content: content && content.trim() ? content.trim() : null,
|
||||
file: fileUrl,
|
||||
@@ -263,6 +276,16 @@ const sendShopChatFileMessage = async (req, res, next) => {
|
||||
readByBuyer: !isOwner
|
||||
})
|
||||
|
||||
sendShopChatPushNotification({
|
||||
shop,
|
||||
senderId: req.user._id,
|
||||
senderRole,
|
||||
buyerId,
|
||||
receiverId: isOwner ? buyerId : shop.owner
|
||||
}).catch((err) => {
|
||||
console.error('[shopChatController] push notification failed:', err.message)
|
||||
})
|
||||
|
||||
return res.status(201).json({ message })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/* eslint-disable camelcase */
|
||||
const mongoose = require('mongoose')
|
||||
const fs = require('fs-extra')
|
||||
const path = require('path')
|
||||
const jwt = require('jsonwebtoken')
|
||||
@@ -7,8 +8,12 @@ const ShopProductListingModel = require('../../../models/ShopProductListingModel
|
||||
const ShopRatingModel = require('../../../models/ShopRatingModel')
|
||||
const ShopFollowModel = require('../../../models/ShopFollowModel')
|
||||
const OrderModel = require('../../../models/OrderModel')
|
||||
const MessageModel = require('../../../models/MessageModel')
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const { maskPhoneNumbers } = require('../../../utils/phoneNumberMasking')
|
||||
const { optimizeImageFile } = require('../../../utils/imageOptimize')
|
||||
const { viewerIsBlockedBy } = require('../../../utils/blockVisibility')
|
||||
const { enrichMessage, emitChatEvents } = require('../../../helpers/chatHelpers')
|
||||
|
||||
const MS_DAY = 24 * 60 * 60 * 1000
|
||||
const ANALYTICS_RANGE_DAYS = { '7d': 7, '30d': 30, '90d': 90, all: null }
|
||||
@@ -400,6 +405,76 @@ const submitShop = async (req, res, next) => {
|
||||
}
|
||||
}
|
||||
|
||||
/** عینِ sendProductToUsers توی shopProductController.js — پیامهای چتِ معمولی
|
||||
* (MessageModel) با یه پیامِ sharedShop برای هرکدوم از گیرندهها؛ برای ارسالِ خودِ
|
||||
* فروشگاه (نه یه کالای خاص) از دکمهی «ارسال» کنارِ اشتراکگذاری */
|
||||
const sendShopToUsers = async (req, res, next) => {
|
||||
try {
|
||||
const senderId = req.user._id
|
||||
const { receiverIds } = req.body
|
||||
|
||||
if (!Array.isArray(receiverIds) || !receiverIds.length) {
|
||||
return shopError(res, 400, 'حداقل یک گیرنده انتخاب کنید')
|
||||
}
|
||||
|
||||
const uniqueReceivers = [
|
||||
...new Set(
|
||||
receiverIds
|
||||
.map(String)
|
||||
.filter((id) => mongoose.Types.ObjectId.isValid(id) && id !== String(senderId))
|
||||
)
|
||||
].slice(0, 50)
|
||||
|
||||
if (!uniqueReceivers.length) {
|
||||
return shopError(res, 400, 'گیرنده معتبر یافت نشد')
|
||||
}
|
||||
|
||||
const shop = await ShopModel.findById(req.params.id)
|
||||
if (!shop) return shopError(res, 404, 'فروشگاه یافت نشد')
|
||||
|
||||
const sharedShop = {
|
||||
shopId: String(shop._id),
|
||||
name: shop.name,
|
||||
logo: shop.logo || '',
|
||||
url: `https://modstagram.com/shops/profile/${shop._id}`
|
||||
}
|
||||
|
||||
const content = JSON.stringify({ sharedShop })
|
||||
const io = req.app.get('io')
|
||||
|
||||
let sentCount = 0
|
||||
for (const receiverId of uniqueReceivers) {
|
||||
const receiver = await UserModel.findById(receiverId).select('blocked_users').lean()
|
||||
if (!receiver) continue
|
||||
if (viewerIsBlockedBy(receiver, senderId)) continue
|
||||
|
||||
const newMessage = new MessageModel({
|
||||
senderId,
|
||||
receiverId,
|
||||
content
|
||||
})
|
||||
await newMessage.save()
|
||||
|
||||
if (io) {
|
||||
const formatted = await enrichMessage(newMessage)
|
||||
emitChatEvents(io, formatted, senderId, receiverId)
|
||||
}
|
||||
sentCount += 1
|
||||
}
|
||||
|
||||
if (!sentCount) {
|
||||
return shopError(res, 400, 'ارسال به هیچ گیرندهای انجام نشد')
|
||||
}
|
||||
|
||||
return res.status(200).json({
|
||||
message: `فروشگاه به ${sentCount} نفر ارسال شد`,
|
||||
sentCount
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
createDraftShop,
|
||||
getMyShops,
|
||||
@@ -412,5 +487,6 @@ module.exports = {
|
||||
updateShopLocation,
|
||||
updateShopContact,
|
||||
toggleShopFollow,
|
||||
submitShop
|
||||
submitShop,
|
||||
sendShopToUsers
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user