heruvym/service/service.go
2024-11-26 02:11:24 +03:00

1135 lines
27 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package service
import (
"context"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"github.com/go-redis/redis/v8"
"heruvym/dal/minio"
"heruvym/dal/mongo"
"heruvym/jwt_adapter"
"heruvym/middleware"
"heruvym/model"
"heruvym/tools"
"heruvym/utils"
"io"
"net/http"
"strings"
"sync"
"time"
"github.com/rs/xid"
"gitea.pena/PenaSide/hlog"
tb "gopkg.in/tucnak/telebot.v2"
)
type Heruvym struct {
logger hlog.Logger
dal *mongo.DAL
bs *minio.BlobStore
notifier *tb.Bot
tgChatID int64
redisClient *redis.Client
}
func New(
blobs *minio.BlobStore,
dataAccessLayer *mongo.DAL,
log hlog.Logger,
notifier *tb.Bot,
tgChatID int64, redisClient *redis.Client) *Heruvym {
return &Heruvym{
logger: log.Module("Service"),
dal: dataAccessLayer,
bs: blobs,
notifier: notifier,
tgChatID: tgChatID,
redisClient: redisClient,
}
}
func (h Heruvym) Register(m *http.ServeMux) *http.ServeMux {
m.HandleFunc("/create", h.CreateTicket)
m.HandleFunc("/subscribe", tools.SseWrapper(h.GetList))
m.HandleFunc("/ticket", tools.SseWrapper(h.Subscribe))
m.HandleFunc("/send", tools.HandlerWrapper(h.PutMessage))
m.HandleFunc("/getTickets", tools.HandlerWrapper(h.GetTickets))
m.HandleFunc("/getMessages", tools.HandlerWrapper(h.GetMessages))
m.HandleFunc("/pick", tools.HandlerWrapper(h.Pick))
m.HandleFunc("/delegate", tools.HandlerWrapper(h.Delegate))
m.HandleFunc("/vote", tools.HandlerWrapper(h.Vote))
m.HandleFunc("/close", tools.HandlerWrapper(h.CloseTicket))
return m
}
type CreateTicketReq struct {
Title string `json:"Title"`
Message string `json:"Message"`
}
type CreateTicketResp struct {
Ticket string `json:"Ticket"`
Sess string `json:"sess"`
}
func (h *Heruvym) CreateTicket(w http.ResponseWriter, r *http.Request) {
defer func() {
if err := r.Body.Close(); err != nil {
h.logger.Emit(ErrorClose{
Err: err,
})
}
}()
var (
err error
request CreateTicketReq
)
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
http.Error(w, "Invalid json", http.StatusBadRequest)
return
}
if request.Title == "" {
http.Error(w, "No Title", http.StatusBadRequest)
return
}
if request.Message == "" {
http.Error(w, "No Message", http.StatusBadRequest)
return
}
ctx := r.Context()
session := jwt_adapter.Get(ctx)
if session == nil {
http.Error(w, "No session", http.StatusUnauthorized)
return
}
var (
ticketID string
tickets []model.Ticket
role = jwt_adapter.GetRole(ctx)
)
if role == "" {
tickets, _, err = h.dal.GetTickets4Sess(ctx, session.Id)
}
if err != nil || len(tickets) == 0 {
ticketID, err = h.dal.CreateTicket(
ctx,
session.Id,
session.Id,
r.Header["Origin"][0],
request.Title,
request.Message,
[]string{},
)
if err != nil {
http.Error(w, "CannotCreateTicket", http.StatusInternalServerError)
return
}
if _, err := h.dal.PutMessage(ctx,
request.Message,
session.Id,
session.Id,
ticketID,
[]string{},
); err != nil {
http.Error(w, "CannotCreateMessage", http.StatusInternalServerError)
return
}
domain := ctx.Value(middleware.HostKey).(string)
if domain == "" {
fmt.Println("domain is nil err")
}
go func() {
if session.Id != "" && role != "admin" {
if err == nil && h.notifier != nil {
var userLink, supportLink string
if session.StandardClaims.Issuer != "" {
fmt.Println("MABNAT", domain)
if domain[0] == 's' {
userLink = fmt.Sprintf("https://sadmin.pena/users/%s", session.Id)
supportLink = fmt.Sprintf("https://sadmin.pena/support/%s", ticketID)
} else {
userLink = fmt.Sprintf("https://admin.pena/users/%s", session.Id)
supportLink = fmt.Sprintf("https://admin.pena/support/%s", ticketID)
}
} else {
if domain[0] == 's' {
supportLink = fmt.Sprintf("https://sadmin.pena/support/%s", ticketID)
} else {
supportLink = fmt.Sprintf("https://admin.pena/support/%s", ticketID)
}
userLink = "незарегистрированного пользователя"
}
message := fmt.Sprintf("Вам пришло сообщение от %s сссылка на пользователя с %s, ccылка на чат - %s",
userLink, domain, supportLink)
if _, err := h.notifier.Send(tb.ChatID(h.tgChatID), message); err != nil {
fmt.Println("CAN NOT NOTIFY", err)
}
return
}
}
}()
} else {
ticketID = tickets[0].ID
}
response, err := json.Marshal(CreateTicketResp{Ticket: ticketID, Sess: session.Id})
if err != nil {
h.logger.Emit(ErrorMarshal{
Err: err,
})
http.Error(w, "CannotMarshalMessage", http.StatusInternalServerError)
return
}
if _, err := w.Write(response); err != nil {
h.logger.Emit(ErrorMarshal{
Err: err,
})
return
}
}
var _ tools.DataEmitter = (&Heruvym{}).GetList
func (h *Heruvym) GetList(ctx context.Context) chan interface{} {
fmt.Println("GetList")
defer func() {
if rec := recover(); rec != nil {
fmt.Println(rec)
}
}()
sess := jwt_adapter.Get(ctx)
fmt.Println("sess", sess)
if sess == nil {
return nil
}
output := make(chan interface{})
if sess.Id == "" {
go h.unauthorizedTickets(ctx, sess.Id, output)
} else {
role := jwt_adapter.GetRole(ctx)
fmt.Println("ALL TICKETS Sess ", sess.Id, role)
if role == "admin" || role == "manager" {
go h.allTickets(ctx, output)
} else {
go h.userTickets(ctx, sess.Id, output)
}
}
return output
}
func (h *Heruvym) allTickets(ctx context.Context, output chan interface{}) {
defer func() {
if v := recover(); v != nil {
fmt.Println("AllTicketsRec", v)
}
}()
//data, count, err := h.dal.YieldTickets(ctx, 20)
//
//if err != nil {
// output <- errors.New("cannot get tickets:" + err.Error())
// return
//}
//
//if data != nil {
// output <- GetTicketsResp{data, count}
//}
if err := h.dal.WatchAllTickets(ctx, func(ticket model.Ticket) error {
output <- ticket
return nil
}); err != nil {
output <- errors.New("cannot watch all tickets" + err.Error())
}
}
func (h *Heruvym) userTickets(ctx context.Context, userID string, output chan interface{}) {
defer func() {
if v := recover(); v != nil {
fmt.Println("USERTICKS", v)
}
}()
data, count, err := h.dal.YieldUserTickets(ctx, userID, 20, 0)
if err != nil {
output <- errors.New("cannot get tickets:" + err.Error())
return
}
if data != nil {
output <- GetTicketsResp{data, count}
}
if err := h.dal.WatchTickets(ctx, userID, func(ticket model.Ticket) error {
output <- ticket
return nil
}); err != nil {
output <- errors.New("cannot watch tickets")
return
}
}
func (h *Heruvym) hasNoRole(output chan interface{}) {
output <- errors.New("no role in profile")
}
func (h *Heruvym) unauthorizedTickets(ctx context.Context, sess string, output chan interface{}) {
//defer close(output)
tickets, count, err := h.dal.GetTickets4Sess(ctx, sess)
if err != nil {
output <- errors.New("no tickets for session")
return
}
if tickets != nil {
output <- GetTicketsResp{tickets, count}
}
}
type ReqPutMessage struct {
Message string `json:"message"`
TicketID string `json:"ticket"`
Files []string `json:"files"`
Lang string `json:"lang"`
}
func (h *Heruvym) PutMessage(
ctx context.Context,
request ReqPutMessage,
) (interface{}, int) {
sess := jwt_adapter.Get(ctx)
fmt.Println("PUTMES", sess)
request.Files = []string{}
domain := ctx.Value(middleware.HostKey).(string)
if domain == "" {
fmt.Println("domain is nil err")
return errors.New("domain is nil"), http.StatusBadRequest
}
message, err := h.dal.PutMessage(
ctx,
request.Message,
sess.Id,
sess.Id,
request.TicketID,
[]string{},
)
fmt.Println("PUTMES00", err)
if err != nil {
fmt.Println("PUTMES1", err)
return errors.New("can not put message"), http.StatusInternalServerError
}
role := jwt_adapter.GetRole(ctx)
go func() {
if sess.Id != "" && role != "admin" {
if err == nil && h.notifier != nil {
var userLink,supportLink string
if sess.StandardClaims.Issuer != "" {
fmt.Println("MABNAT", domain)
if domain[0] == 's' {
userLink = fmt.Sprintf("https://sadmin.pena/users/%s", sess.Id)
supportLink = fmt.Sprintf("https://sadmin.pena/support/%s", request.TicketID)
} else {
userLink = fmt.Sprintf("https://admin.pena/users/%s", sess.Id)
supportLink = fmt.Sprintf("https://admin.pena/support/%s", request.TicketID)
}
} else {
if domain[0] == 's' {
supportLink = fmt.Sprintf("https://sadmin.pena/support/%s", request.TicketID)
} else {
supportLink = fmt.Sprintf("https://admin.pena/support/%s", request.TicketID)
}
userLink = "незарегистрированного пользователя"
}
message := fmt.Sprintf("Вам пришло сообщение от %s сссылка на пользователя с %s, ссылка на чат - %s",
userLink, domain, supportLink)
if _, err := h.notifier.Send(tb.ChatID(h.tgChatID), message); err != nil {
fmt.Println("CAN NOT NOTIFY", err)
}
return
}
}
}()
if err := h.dal.UpdateTopMessage(ctx, request.TicketID, message); err != nil {
fmt.Println("PUTMES01", err, request.TicketID, message)
//return errors.New("can not update ticket"), http.StatusInternalServerError
}
fmt.Println("PUTMES03")
return nil, http.StatusOK
}
type ReqScreenshot struct {
TicketID string `json:"ticket"`
Lang string `json:"lang"`
}
func (h *Heruvym) RequestScreenshot(
ctx context.Context,
request ReqScreenshot,
) (interface{}, int) {
sess := jwt_adapter.Get(ctx)
_, err := h.dal.PutSCRequest(
ctx,
sess.Id,
sess.Id,
request.TicketID,
)
if err != nil {
return errors.New("can not put message"), http.StatusInternalServerError
}
return nil, http.StatusOK
}
var _ tools.DataEmitter = (&Heruvym{}).Subscribe
func (h *Heruvym) Subscribe(ctx context.Context) chan interface{} {
sess := jwt_adapter.Get(ctx)
fmt.Println("SESS Subsc", sess)
ticketID := ctx.Value(tools.ContextURLKey).(string)
output := make(chan interface{})
if sess.Id == "" {
go func() {
ticket, err := h.dal.GetTicket4Sess(ctx, ticketID, sess.Id)
if err != nil || ticket == nil {
output <- errors.New("no tickets 4 session")
return
}
/*if err := h.dal.YieldMessages(ctx, ticketID, func(message model.Message) error {
output <- message
fmt.Println("OOOOOOLd")
//if err := h.dal.SetShown(ctx, message.ID, sess.Session); err != nil {
//
// output <- errors.New("cannot show message " + err.Error())
// return err
//}
return nil
}); err != nil {
output <- errors.New("cannot read messages " + err.Error())
}*/
if err := h.dal.WatchMessages(ctx, ticketID,
func(message model.Message) error {
output <- message
//if err := h.dal.SetShown(ctx, message.ID, sess.Session); err != nil {
// fmt.Println("3", err)
// output <- errors.New("cannot show watch message " + err.Error())
// return err
//}
return nil
}); err != nil {
fmt.Println("4", err)
output <- errors.New("cannot watch messages " + err.Error())
}
}()
} else {
role := jwt_adapter.GetRole(ctx)
if role == "admin" || role == "manager" {
go func() {
if err := h.dal.YieldMessages(ctx, ticketID, func(message model.Message) error {
output <- message
//if err := h.dal.SetShown(ctx, message.ID, sess.User); err != nil {
// fmt.Println("2", err)
// output <- errors.New("cannot show message " + err.Error())
// return err
//}
return nil
}); err != nil {
fmt.Println("1", err)
output <- errors.New("cannot read messages " + err.Error())
}
if err := h.dal.WatchMessages(ctx, ticketID,
func(message model.Message) error {
output <- message
//if err := h.dal.SetShown(ctx, message.ID, sess.Session); err != nil {
// fmt.Println("3", err)
// output <- errors.New("cannot show watch message " + err.Error())
// return err
//}
return nil
}); err != nil {
fmt.Println("4", err)
output <- errors.New("cannot watch messages " + err.Error())
}
}()
} else {
go func() {
defer func() {
if v := recover(); v != nil {
fmt.Println("heryvym panic", v)
}
}()
ticket, err := h.dal.GetTicket4User(ctx, ticketID, sess.Id)
if err != nil || ticket == nil {
output <- errors.New("no tickets 4 user")
}
/*if err := h.dal.YieldMessages(ctx, ticketID, func(message model.Message) error {
output <- message
//if err := h.dal.SetShown(ctx, message.ID, sess.User); err != nil {
// fmt.Println("2", err)
// output <- errors.New("cannot show message " + err.Error())
// return err
//}
return nil
}); err != nil {
fmt.Println("1", err)
output <- errors.New("cannot read messages " + err.Error())
}*/
if err := h.dal.WatchMessages(ctx, ticketID,
func(message model.Message) error {
output <- message
//if err := h.dal.SetShown(ctx, message.ID, sess.Session); err != nil {
// fmt.Println("3", err)
// output <- errors.New("cannot show watch message " + err.Error())
// return err
//}
return nil
}); err != nil {
fmt.Println("4", err)
output <- errors.New("cannot watch messages " + err.Error())
}
}()
}
}
return output
}
func (h *Heruvym) handleOwnMessages(output chan interface{}) {
defer close(output)
}
type GetTicketsReq struct {
Amount int64 `json:"amt"`
Page int64 `json:"page"`
Search string `json:"srch"`
Status string `json:"status"`
}
type GetTicketsResp struct {
Data []model.Ticket `json:"data"`
Count int64 `json:"count"`
}
func (h *Heruvym) GetTickets(
ctx context.Context,
request GetTicketsReq) (GetTicketsResp, int) {
role := jwt_adapter.GetRole(ctx)
if role == "admin" {
result, count, err := h.dal.GetTicketPage(ctx,
request.Status,
request.Search,
request.Amount,
request.Page,
)
if err != nil {
return GetTicketsResp{}, http.StatusNoContent
}
return GetTicketsResp{
Data: *result,
Count: count,
}, http.StatusOK
} else {
sess := jwt_adapter.Get(ctx)
result, count, err := h.dal.YieldUserTickets(ctx, sess.Id, request.Amount, request.Page*request.Amount)
if err != nil {
return GetTicketsResp{}, http.StatusNoContent
}
return GetTicketsResp{
Data: result,
Count: count,
}, http.StatusOK
}
}
type GetMessagesReq struct {
Amount int64 `json:"amt"`
Page int64 `json:"page"`
Search string `json:"srch"`
TicketID string `json:"ticket"`
}
func (h *Heruvym) GetMessages(
ctx context.Context,
request GetMessagesReq) ([]model.Message, int) {
result, err := h.dal.GetMessagesPage(ctx,
request.Search,
request.TicketID,
request.Amount,
request.Page,
)
if err != nil {
return nil, http.StatusNoContent
}
return result, http.StatusOK
}
type CloseTicketReq struct {
TicketID string `json:"ticket"`
}
type CloseTicketResp struct {
TicketID string `json:"ticket"`
}
func (h *Heruvym) CloseTicket(ctx context.Context, req CloseTicketReq) (*CloseTicketResp, int) {
if err := h.dal.SetTicketStatus(ctx, req.TicketID, model.StateClose); err != nil {
return nil, http.StatusBadRequest
}
if _, err := h.dal.PutMessage(ctx, "close", "close", "close", req.TicketID, []string{}); err != nil {
return nil, http.StatusBadRequest
}
return &CloseTicketResp{
TicketID: req.TicketID,
}, http.StatusOK
}
type VoteReq struct {
TicketID string `json:"ticket"`
Rate int `json:"rate"`
}
func (h *Heruvym) Vote(ctx context.Context, req VoteReq) (error, int) {
if err := h.dal.SetRate(ctx, req.TicketID, req.Rate); err != nil {
return err, http.StatusBadRequest
}
return nil, http.StatusOK
}
type PickReq struct {
TicketID string `json:"ticket"`
}
func (h *Heruvym) Pick(ctx context.Context, req PickReq) (error, int) {
sess := jwt_adapter.Get(ctx)
if err := h.dal.SetAnswerer(ctx, req.TicketID, sess.Id); err != nil {
return err, http.StatusBadRequest
}
return nil, http.StatusOK
}
type DelegateReq struct {
TicketID string `json:"ticket"`
AnswererID string `json:"answerer"`
}
func (h *Heruvym) Delegate(ctx context.Context, req DelegateReq) (error, int) {
if err := h.dal.SetAnswerer(ctx, req.TicketID, req.AnswererID); err != nil {
return err, http.StatusBadRequest
}
return nil, http.StatusOK
}
// MB Size constants
const (
MB = 1 << 20
)
var fileTypeLimits = map[string]int64{
"image": 5 * MB,
"video": 50 * MB,
"document": 10 * MB,
}
type PutFileReq struct {
Ticket string `json:"ticket"`
}
type PutFileResp struct {
Message string `json:"message"`
}
func (h *Heruvym) PutFile(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
sess := jwt_adapter.Get(r.Context())
if sess == nil {
w.WriteHeader(http.StatusBadRequest)
if _, err := w.Write([]byte("not authorized")); err != nil {
fmt.Println("CAN NOT WRITE", err)
}
return
}
TimeKey := fmt.Sprintf("sendLockHeruvym:%s", sess.Id)
isNewKey, err := h.redisClient.SetNX(r.Context(), TimeKey, time.Now().Unix(), 30*time.Second).Result()
if err != nil {
fmt.Println("failed check last upload time in Redis:", err)
w.WriteHeader(http.StatusInternalServerError)
if _, err := w.Write([]byte("internal server error")); err != nil {
fmt.Println("CAN NOT WRITE", err)
}
return
}
if !isNewKey {
w.WriteHeader(http.StatusTooManyRequests)
if _, err := w.Write([]byte("file upload limit exceeded")); err != nil {
fmt.Println("CAN NOT WRITE", err)
}
return
}
if err := r.ParseMultipartForm(10 * MB); err != nil {
w.WriteHeader(http.StatusBadRequest)
if _, err := w.Write([]byte("can not parse multipart " + err.Error())); err != nil {
fmt.Println("CAN NOT WRITE", err)
}
return
}
if r.MultipartForm == nil {
w.WriteHeader(http.StatusBadRequest)
if _, err := w.Write([]byte("no multipart")); err != nil {
fmt.Println("CAN NOT WRITE", err)
}
return
}
if r.MultipartForm.File == nil {
w.WriteHeader(http.StatusBadRequest)
if _, err := w.Write([]byte("no file")); err != nil {
fmt.Println("CAN NOT WRITE", err)
}
return
}
for _, files := range r.MultipartForm.File {
for _, fileHeader := range files {
fileSize := fileHeader.Size
fileType := utils.GetFileType(fileHeader.Filename)
if limit, ok := fileTypeLimits[fileType]; ok {
if fileSize > limit {
w.WriteHeader(http.StatusRequestEntityTooLarge)
if _, err := w.Write([]byte(fileType + " file size exceeds the limit")); err != nil {
fmt.Println("CAN NOT WRITE", err)
}
return
}
} else {
w.WriteHeader(http.StatusNotAcceptable)
if _, err := w.Write([]byte("Unsupported file type")); err != nil {
fmt.Println("CAN NOT WRITE", err)
}
return
}
}
}
filesCount := len(r.MultipartForm.File)
if filesCount == 0 {
w.WriteHeader(http.StatusBadRequest)
if _, err := w.Write([]byte("no files")); err != nil {
fmt.Println("CAN NOT WRITE", err)
}
return
}
var req PutFileReq
req.Ticket = r.MultipartForm.Value["ticket"][0]
var (
fileIDs, filenames []string
errFile error
)
wg := new(sync.WaitGroup)
m := new(sync.Mutex)
wg.Add(filesCount)
for name, file := range r.MultipartForm.File {
file := file
name := name
go func() {
defer wg.Done()
freader, err := file[0].Open()
if err != nil {
fmt.Println("can not open ", err.Error())
}
hash := sha256.New()
if _, err := io.Copy(hash, freader); err != nil {
fmt.Println("error calculating file hash: ", err)
errFile = err
}
_, err = freader.Seek(0, 0)
if err != nil {
fmt.Println("error seeking back to the beginning of the file: ", err)
errFile = err
}
hashInBytes := hash.Sum(nil)
fileHash := hex.EncodeToString(hashInBytes)
splitted := strings.Split(name, ".")
filename := fmt.Sprintf("%s_%s.%s", fileHash, sess.Id, splitted[len(splitted)-1])
defer func() {
if err := freader.Close(); err != nil {
errFile = err
}
}()
exists, err := h.bs.FileExists(r.Context(), filename)
if err != nil {
errFile = err
return
}
if exists {
response := struct {
File string `json:"file"`
}{
File: filename,
}
resp, err := json.Marshal(response)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
if _, err := w.Write([]byte("error marshaling response: " + err.Error())); err != nil {
fmt.Println("CAN NOT WRITE", err)
}
return
}
w.WriteHeader(http.StatusAlreadyReported)
if _, err := w.Write(resp); err != nil {
fmt.Println("CAN NOT WRITE", err)
}
m.Lock()
defer m.Unlock()
fileIDs = append(fileIDs, filename)
filenames = append(filenames, name)
return
}
if err := h.bs.PutFile(
r.Context(),
filename,
freader,
file[0].Size); err != nil {
errFile = err
}
m.Lock()
defer m.Unlock()
fileIDs = append(fileIDs, filename)
filenames = append(filenames, name)
}()
}
wg.Wait()
if len(fileIDs) == 0 {
return
}
if errFile != nil {
w.WriteHeader(http.StatusInternalServerError)
if _, err := w.Write([]byte("can not store files " + errFile.Error())); err != nil {
fmt.Println("CAN NOT WRITE", err)
}
return
}
message, err := h.dal.PutMessage(
r.Context(),
strings.Join(filenames, ", "),
sess.Id,
sess.Id,
req.Ticket,
fileIDs,
)
if err != nil {
for _, filename := range filenames {
if err := h.bs.DeleteFile(r.Context(), filename); err != nil {
fmt.Println("can not delete", err)
}
}
w.WriteHeader(http.StatusInternalServerError)
if _, err := w.Write([]byte("can not store message " + err.Error())); err != nil {
fmt.Println("CAN NOT WRITE", err)
}
return
}
resp, err := json.Marshal(&PutFileResp{Message: message.ID})
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
if _, err := w.Write([]byte("can not marshal resp " + err.Error())); err != nil {
fmt.Println("CAN NOT WRITE", err)
}
return
}
ctx := r.Context()
domain := ctx.Value(middleware.HostKey).(string)
if domain == "" {
fmt.Println("domain is nil err")
}
role := jwt_adapter.GetRole(ctx)
go func() {
if sess.Id != "" && role != "admin" {
if err == nil && h.notifier != nil {
var userLink, supportLink string
if sess.StandardClaims.Issuer != "" {
fmt.Println("MABNAT", domain)
if domain[0] == 's' {
userLink = fmt.Sprintf("https://sadmin.pena/users/%s", sess.Id)
supportLink = fmt.Sprintf("https://sadmin.pena/support/%s", req.Ticket)
} else {
userLink = fmt.Sprintf("https://admin.pena/users/%s", sess.Id)
supportLink = fmt.Sprintf("https://admin.pena/support/%s", req.Ticket)
}
} else {
if domain[0] == 's' {
supportLink = fmt.Sprintf("https://sadmin.pena/support/%s", req.Ticket)
} else {
supportLink = fmt.Sprintf("https://admin.pena/support/%s", req.Ticket)
}
userLink = "незарегистрированного пользователя"
}
message := fmt.Sprintf("Вам пришло сообщение от %s сссылка на пользователя с %s, ccылка на чат - %s",
userLink, domain, supportLink)
if _, err := h.notifier.Send(tb.ChatID(h.tgChatID), message); err != nil {
fmt.Println("CAN NOT NOTIFY", err)
}
return
}
}
}()
if _, err := w.Write(resp); err != nil {
fmt.Println("CAN NOT WRITE", err)
}
w.WriteHeader(http.StatusOK) // Необязательно, т.к. w.Write сам вызывает w.WriteHeader(http.StatusOK) перед выполнением
}
type PutSCReq struct {
Ticket string `json:"ticket"`
}
type PutSCResp struct {
Message string `json:"message"`
}
func (h *Heruvym) PutSC(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
if err := r.ParseMultipartForm(10 * MB); err != nil {
w.WriteHeader(http.StatusBadRequest)
if _, err := w.Write([]byte("can not parse multipart " + err.Error())); err != nil {
fmt.Println("CAN NOT WRITE", err)
}
return
}
if r.MultipartForm == nil {
w.WriteHeader(http.StatusBadRequest)
if _, err := w.Write([]byte("no multipart")); err != nil {
fmt.Println("CAN NOT WRITE", err)
}
return
}
if r.MultipartForm.File == nil {
w.WriteHeader(http.StatusBadRequest)
if _, err := w.Write([]byte("no file")); err != nil {
fmt.Println("CAN NOT WRITE", err)
}
return
}
filesCount := len(r.MultipartForm.File)
if filesCount == 0 {
w.WriteHeader(http.StatusBadRequest)
if _, err := w.Write([]byte("no files")); err != nil {
fmt.Println("CAN NOT WRITE", err)
}
return
}
sess := jwt_adapter.Get(r.Context())
if sess == nil {
w.WriteHeader(http.StatusUnauthorized)
if _, err := w.Write([]byte("not authorized")); err != nil {
fmt.Println("CAN NOT WRITE", err)
}
return
}
var req PutFileReq
req.Ticket = r.MultipartForm.Value["ticket"][0]
var (
fileIDs, filenames []string
errFile error
)
wg := new(sync.WaitGroup)
m := new(sync.Mutex)
wg.Add(filesCount)
for name, file := range r.MultipartForm.File {
file := file
name := name
go func() {
defer wg.Done()
freader, err := file[0].Open()
if err != nil {
fmt.Println("can not open ", err.Error())
}
defer func() {
if err := freader.Close(); err != nil {
errFile = err
}
}()
splitted := strings.Split(name, ".")
filename := fmt.Sprintf("%s.%s", xid.New().String(), splitted[len(splitted)-1])
if err := h.bs.PutFile(
r.Context(),
filename,
freader,
file[0].Size); err != nil {
errFile = err
}
m.Lock()
defer m.Unlock()
fileIDs = append(fileIDs, filename)
filenames = append(filenames, name)
}()
}
wg.Wait()
if errFile != nil {
w.WriteHeader(http.StatusInternalServerError)
if _, err := w.Write([]byte("can not store files " + errFile.Error())); err != nil {
fmt.Println("CAN NOT WRITE", err)
}
return
}
message, err := h.dal.PutSCResponse(
r.Context(),
strings.Join(filenames, ", "),
sess.Id,
sess.Id,
req.Ticket,
fileIDs,
)
if err != nil {
for _, filename := range filenames {
if err := h.bs.DeleteFile(r.Context(), filename); err != nil {
fmt.Println("can not delete", err)
}
}
w.WriteHeader(http.StatusInternalServerError)
if _, err := w.Write([]byte("can not store message " + err.Error())); err != nil {
fmt.Println("CAN NOT WRITE", err)
}
return
}
resp, err := json.Marshal(&PutFileResp{Message: message.ID})
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
if _, err := w.Write([]byte("can not marshal resp " + err.Error())); err != nil {
fmt.Println("CAN NOT WRITE", err)
}
return
}
if _, err := w.Write(resp); err != nil {
fmt.Println("CAN NOT WRITE", err)
}
w.WriteHeader(http.StatusOK)
}
type ShownReq struct {
ID string `json:"id"`
}
func (h *Heruvym) SetShown(ctx context.Context, req ShownReq) (error, int) {
return h.dal.SetShown(ctx, req.ID, "me"), http.StatusOK
}