Skip to content
Snippets Groups Projects
Select Git revision
  • 57ebc48e28a6688c5e07235b3ead6856575a88c9
  • master default protected
  • v1.4.5
  • v1.4.4
  • v1.4.3
  • v1.4.2
  • v1.4.1
  • v1.4.0
  • v1.3.10
  • v1.3.9
  • v1.3.8
  • v1.3.7
  • v1.3.6
  • v1.3.5
  • v1.3.4
  • v1.3.3
  • v1.3.2
  • v1.3.1
  • v1.3.0
  • v1.2.9
  • v1.2.8
  • v1.2.7
22 results

tag.go

Blame
  • tag.go 4.22 KiB
    package store
    
    import (
    	"encoding/json"
    	"fmt"
    	log "github.com/sirupsen/logrus"
    	"os"
    	"time"
    )
    
    const (
    	// ArtistType is the tag type artist.
    	ArtistType = "artist"
    	// CharacterType is the tag type character.
    	CharacterType = "character"
    	// CopyrightType is the tag type copyright.
    	CopyrightType = "copyright"
    	// MetaType is the tag type meta.
    	MetaType = "meta"
    	// GenericType is the tag type generic.
    	GenericType = "generic"
    )
    
    // Tag represents metadata of a tag.
    type Tag struct {
    	Type         string    `json:"type"`
    	CreationTime time.Time `json:"creation_time"`
    }
    
    // Tags returns a slice of tag names.
    func (s *Store) Tags() []string {
    	var tags []string
    	if entries, err := os.ReadDir(s.TagsDir()); err != nil {
    		s.fatalClose(fmt.Sprintf("Error reading tags, %s", err))
    	} else {
    		for _, entry := range entries {
    			if entry.IsDir() {
    				tags = append(tags, entry.Name())
    			}
    		}
    	}
    	return tags
    }
    
    // Tag returns a slice of image snowflakes in a specific tag.
    func (s *Store) Tag(tag string) []string {
    	if !nameRegex.MatchString(tag) || !s.dir(s.TagPath(tag)) {
    		return nil
    	}
    	var images []string
    	if entries, err := os.ReadDir(s.TagPath(tag)); err != nil {
    		s.fatalClose(fmt.Sprintf("Error reading tag %s, %s", tag, err))
    	} else {
    		for _, entry := range entries {
    			if entry.Name() == infoJson {
    				continue
    			}
    			images = append(images, entry.Name())
    		}
    	}
    	return images
    }
    
    // TagCreate creates a tag and returns ok value.
    func (s *Store) TagCreate(tag string) bool {
    	if len(tag) > 128 || !nameRegex.MatchString(tag) {
    		return false
    	}
    	if !s.dir(s.TagPath(tag)) {
    		s.getLock("tag_" + tag).Lock()
    		defer s.getLock("tag_" + tag).Unlock()
    		if err := os.Mkdir(s.TagPath(tag), s.PermissionDir); err != nil {
    			s.fatalClose(fmt.Sprintf("Error creating tag %s, %s", tag, err))
    		}
    		if payload, err := json.Marshal(Tag{Type: GenericType, CreationTime: time.Now().UTC()}); err != nil {
    			s.fatalClose(fmt.Sprintf("Error generating tag %s metadata, %s", tag, err))
    		} else {
    			if err = os.WriteFile(s.TagMetadataPath(tag), payload, s.PermissionFile); err != nil {
    				s.fatalClose(fmt.Sprintf("Error writing tag %s metadata, %s", tag, err))
    			}
    		}
    		log.Infof("Tag %s created.", tag)
    		return true
    	}
    	return true
    }
    
    // TagDestroy removes all references from a tag and removes it.
    func (s *Store) TagDestroy(tag string) {
    	if !nameRegex.MatchString(tag) || !s.dir(s.TagPath(tag)) {
    		return
    	}
    
    	flakes := s.Tag(tag)
    	for _, flake := range flakes {
    		s.ImageTagRemove(flake, tag)
    	}
    	if err := os.Remove(s.TagMetadataPath(tag)); err != nil {
    		s.fatalClose(fmt.Sprintf("Error removing tag %s metadata, %s", tag, err))
    	}
    	if err := os.Remove(s.TagPath(tag)); err != nil {
    		s.fatalClose(fmt.Sprintf("Error removing tag %s, %s", tag, err))
    	}
    	log.Infof("Tag %s destroyed.", tag)
    }
    
    // TagInfo returns information of a tag.
    func (s *Store) TagInfo(tag string) Tag {
    	if !nameRegex.MatchString(tag) || !s.file(s.TagMetadataPath(tag)) {
    		return Tag{}
    	}
    
    	s.getLock("tag_" + tag).RLock()
    	defer s.getLock("tag_" + tag).RUnlock()
    	if payload, err := os.ReadFile(s.TagMetadataPath(tag)); err != nil {
    		s.fatalClose(fmt.Sprintf("Error reading tag %s metadata, %s", tag, err))
    	} else {
    		var info Tag
    		if err = json.Unmarshal(payload, &info); err != nil {
    			s.fatalClose(fmt.Sprintf("Error parsing tag %s metadata, %s", tag, err))
    		} else {
    			return info
    		}
    	}
    	return Tag{}
    }
    
    // TagType sets type of a tag.
    func (s *Store) TagType(tag, t string) {
    	if !nameRegex.MatchString(tag) || !s.file(s.TagMetadataPath(tag)) {
    		return
    	}
    
    	s.getLock("tag_" + tag).Lock()
    	defer s.getLock("tag_" + tag).Unlock()
    
    	if t != ArtistType &&
    		t != CharacterType &&
    		t != CopyrightType &&
    		t != GenericType &&
    		t != MetaType {
    		log.Warnf("Invalid tag change on tag %s, got %s, expecting {%s,%s,%s,%s,%s}", tag, t,
    			ArtistType, CharacterType, CopyrightType, GenericType, MetaType)
    		return
    	}
    	info := s.TagInfo(tag)
    	info.Type = t
    	if payload, err := json.Marshal(info); err != nil {
    		s.fatalClose(fmt.Sprintf("Error updating tag %s metadata, %s", tag, err))
    	} else {
    		if err = os.WriteFile(s.TagMetadataPath(tag), payload, s.PermissionFile); err != nil {
    			s.fatalClose(fmt.Sprintf("Error writing tag %s metadata, %s", tag, err))
    		}
    	}
    	log.Infof("Tag %s type set to %s.", tag, t)
    }