github.com/e154/smart-home@v0.17.2-0.20240311175135-e530a6e5cd45/db/image.go (about)

     1  // This file is part of the Smart Home
     2  // Program complex distribution https://github.com/e154/smart-home
     3  // Copyright (C) 2016-2023, Filippov Alex
     4  //
     5  // This library is free software: you can redistribute it and/or
     6  // modify it under the terms of the GNU Lesser General Public
     7  // License as published by the Free Software Foundation; either
     8  // version 3 of the License, or (at your option) any later version.
     9  //
    10  // This library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13  // Library General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Lesser General Public
    16  // License along with this library.  If not, see
    17  // <https://www.gnu.org/licenses/>.
    18  
    19  package db
    20  
    21  import (
    22  	"context"
    23  	"database/sql"
    24  	"fmt"
    25  	"strings"
    26  	"time"
    27  
    28  	"github.com/jackc/pgerrcode"
    29  	"github.com/jackc/pgx/v5/pgconn"
    30  
    31  	"github.com/e154/smart-home/common/apperr"
    32  
    33  	"github.com/pkg/errors"
    34  	"gorm.io/gorm"
    35  )
    36  
    37  // Images ...
    38  type Images struct {
    39  	Db *gorm.DB
    40  }
    41  
    42  // Image ...
    43  type Image struct {
    44  	Id        int64 `gorm:"primary_key"`
    45  	Thumb     string
    46  	Image     string
    47  	MimeType  string
    48  	Title     string
    49  	Size      int64
    50  	Name      string
    51  	CreatedAt time.Time `gorm:"<-:create"`
    52  }
    53  
    54  // TableName ...
    55  func (m *Image) TableName() string {
    56  	return "images"
    57  }
    58  
    59  // Add ...
    60  func (n Images) Add(ctx context.Context, v *Image) (id int64, err error) {
    61  	if err = n.Db.WithContext(ctx).Create(&v).Error; err != nil {
    62  		var pgErr *pgconn.PgError
    63  		if errors.As(err, &pgErr) {
    64  			switch pgErr.Code {
    65  			case pgerrcode.UniqueViolation:
    66  				if strings.Contains(pgErr.Message, "images_pkey") {
    67  					err = errors.Wrap(apperr.ErrImageAdd, fmt.Sprintf("image name \"%d\" not unique", v.Id))
    68  					return
    69  				}
    70  			default:
    71  				fmt.Printf("unknown code \"%s\"\n", pgErr.Code)
    72  			}
    73  		}
    74  		err = errors.Wrap(apperr.ErrImageAdd, err.Error())
    75  		return
    76  	}
    77  	id = v.Id
    78  	return
    79  }
    80  
    81  // GetById ...
    82  func (n Images) GetById(ctx context.Context, id int64) (v *Image, err error) {
    83  	v = &Image{Id: id}
    84  	if err = n.Db.WithContext(ctx).First(&v).Error; err != nil {
    85  		if errors.Is(err, gorm.ErrRecordNotFound) {
    86  			err = errors.Wrap(apperr.ErrImageNotFound, fmt.Sprintf("id \"%d\"", id))
    87  			return
    88  		}
    89  		err = errors.Wrap(apperr.ErrImageGet, err.Error())
    90  	}
    91  	return
    92  }
    93  
    94  // GetByImageName ...
    95  func (n Images) GetByImageName(ctx context.Context, imageName string) (v *Image, err error) {
    96  	v = &Image{}
    97  	if err = n.Db.WithContext(ctx).Model(v).Where("image = ?", imageName).First(&v).Error; err != nil {
    98  		if errors.Is(err, gorm.ErrRecordNotFound) {
    99  			err = errors.Wrap(apperr.ErrImageNotFound, fmt.Sprintf("name \"%s\"", imageName))
   100  			return
   101  		}
   102  		err = errors.Wrap(apperr.ErrImageGet, err.Error())
   103  		return
   104  	}
   105  	return
   106  }
   107  
   108  // Update ...
   109  func (n Images) Update(ctx context.Context, m *Image) (err error) {
   110  	err = n.Db.WithContext(ctx).Model(&Image{Id: m.Id}).Updates(map[string]interface{}{
   111  		"title": m.Title,
   112  		"Name":  m.Name,
   113  	}).Error
   114  	if err != nil {
   115  		err = errors.Wrap(apperr.ErrImageUpdate, err.Error())
   116  		return
   117  	}
   118  	return
   119  }
   120  
   121  // Delete ...
   122  func (n Images) Delete(ctx context.Context, mapId int64) (err error) {
   123  	if err = n.Db.WithContext(ctx).Delete(&Image{Id: mapId}).Error; err != nil {
   124  		err = errors.Wrap(apperr.ErrImageDelete, err.Error())
   125  		return
   126  	}
   127  	return
   128  }
   129  
   130  // List ...
   131  func (n *Images) List(ctx context.Context, limit, offset int, orderBy, sort string) (list []*Image, total int64, err error) {
   132  
   133  	if err = n.Db.WithContext(ctx).Model(Image{}).Count(&total).Error; err != nil {
   134  		err = errors.Wrap(apperr.ErrImageList, err.Error())
   135  		return
   136  	}
   137  
   138  	list = make([]*Image, 0)
   139  	err = n.Db.WithContext(ctx).
   140  		Limit(limit).
   141  		Offset(offset).
   142  		Order(fmt.Sprintf("%s %s", sort, orderBy)).
   143  		Find(&list).
   144  		Error
   145  
   146  	if err != nil {
   147  		err = errors.Wrap(apperr.ErrImageList, err.Error())
   148  		return
   149  	}
   150  	return
   151  }
   152  
   153  // ImageFilterList ...
   154  type ImageFilterList struct {
   155  	Date  string `json:"date"`
   156  	Count int    `json:"count"`
   157  }
   158  
   159  // GetFilterList ...
   160  func (n *Images) GetFilterList(ctx context.Context) (images []*ImageFilterList, err error) {
   161  
   162  	image := &Image{}
   163  	var rows *sql.Rows
   164  	rows, err = n.Db.WithContext(ctx).Raw(`
   165  SELECT
   166  	to_char(created_at,'YYYY-mm-dd') as date, COUNT( created_at) as count
   167  FROM ` + image.TableName() + `
   168  GROUP BY date
   169  ORDER BY date`).Rows()
   170  
   171  	if err != nil {
   172  		err = errors.Wrap(apperr.ErrImageList, err.Error())
   173  		return
   174  	}
   175  
   176  	for rows.Next() {
   177  		item := &ImageFilterList{}
   178  		_ = rows.Scan(&item.Date, &item.Count)
   179  		images = append(images, item)
   180  	}
   181  
   182  	return
   183  }
   184  
   185  // GetAllByDate ...
   186  func (n *Images) GetAllByDate(ctx context.Context, filter string) (images []*Image, err error) {
   187  
   188  	//fmt.Println("filter", filter)
   189  
   190  	images = make([]*Image, 0)
   191  	image := &Image{}
   192  	err = n.Db.WithContext(ctx).Raw(`
   193  SELECT *
   194  FROM `+image.TableName()+`
   195  WHERE to_char(created_at,'YYYY-mm-dd') = ?
   196  ORDER BY created_at`, filter).
   197  		Find(&images).
   198  		Error
   199  
   200  	if err != nil {
   201  		err = errors.Wrap(apperr.ErrImageList, err.Error())
   202  	}
   203  	return
   204  }
   205  
   206  // AddMultiple ...
   207  func (n *Images) AddMultiple(ctx context.Context, images []*Image) (err error) {
   208  	if err = n.Db.WithContext(ctx).Create(&images).Error; err != nil {
   209  		var pgErr *pgconn.PgError
   210  		if errors.As(err, &pgErr) {
   211  			switch pgErr.Code {
   212  			case pgerrcode.UniqueViolation:
   213  				if strings.Contains(pgErr.Message, "images_pkey") {
   214  					err = errors.Wrap(apperr.ErrImageAdd, "multiple insert")
   215  					return
   216  				}
   217  			default:
   218  				fmt.Printf("unknown code \"%s\"\n", pgErr.Code)
   219  			}
   220  		}
   221  		err = errors.Wrap(apperr.ErrImageAdd, err.Error())
   222  	}
   223  	return
   224  }