← back to egeozcan__mahresources

Function bodies 753 total

All specs Real LLM only Function bodies
application_context.deduplicateUints function · go · L60-L70 (11 LOC)
application_context/associations.go
func deduplicateUints(ids []uint) []uint {
	seen := make(map[uint]struct{}, len(ids))
	result := make([]uint, 0, len(ids))
	for _, id := range ids {
		if _, ok := seen[id]; !ok {
			seen[id] = struct{}{}
			result = append(result, id)
		}
	}
	return result
}
application_context.MahresourcesContext.CreateBlock method · go · L27-L70 (44 LOC)
application_context/block_context.go
func (ctx *MahresourcesContext) CreateBlock(editor *query_models.NoteBlockEditor) (*models.NoteBlock, error) {
	// Validate block type
	bt := block_types.GetBlockType(editor.Type)
	if bt == nil {
		return nil, errors.New("unknown block type: " + editor.Type)
	}

	// Validate content or use default
	if len(editor.Content) == 0 {
		editor.Content = bt.DefaultContent()
	} else if err := bt.ValidateContent(editor.Content); err != nil {
		return nil, err
	}

	block := models.NoteBlock{
		NoteID:   editor.NoteID,
		Type:     editor.Type,
		Position: editor.Position,
		Content:  types.JSON(editor.Content),
		State:    types.JSON(bt.DefaultState()),
	}

	// Use transaction to ensure atomicity of block creation and description sync
	err := ctx.db.Transaction(func(tx *gorm.DB) error {
		if err := tx.Create(&block).Error; err != nil {
			return err
		}

		// Sync first text block to note description within the same transaction
		if editor.Type == "text" {
			if err := syncFirstTextBlockToDescript
application_context.MahresourcesContext.UpdateBlockContent method · go · L86-L123 (38 LOC)
application_context/block_context.go
func (ctx *MahresourcesContext) UpdateBlockContent(blockID uint, content json.RawMessage) (*models.NoteBlock, error) {
	var block models.NoteBlock
	if err := ctx.db.First(&block, blockID).Error; err != nil {
		return nil, err
	}

	// Validate content against block type
	bt := block_types.GetBlockType(block.Type)
	if bt == nil {
		return nil, errors.New("unknown block type: " + block.Type)
	}
	if err := bt.ValidateContent(content); err != nil {
		return nil, err
	}

	block.Content = types.JSON(content)

	// Use transaction to ensure atomicity of content update and description sync
	err := ctx.db.Transaction(func(tx *gorm.DB) error {
		if err := tx.Save(&block).Error; err != nil {
			return err
		}

		// Sync first text block to note description within the same transaction
		if block.Type == "text" {
			if err := syncFirstTextBlockToDescriptionTx(tx, block.NoteID); err != nil {
				log.Printf("Warning: failed to sync description for note %d: %v", block.NoteID, err)
			}
		}
		return nil
application_context.MahresourcesContext.UpdateBlockState method · go · L126-L143 (18 LOC)
application_context/block_context.go
func (ctx *MahresourcesContext) UpdateBlockState(blockID uint, state json.RawMessage) (*models.NoteBlock, error) {
	var block models.NoteBlock
	if err := ctx.db.First(&block, blockID).Error; err != nil {
		return nil, err
	}

	// Validate state against block type
	bt := block_types.GetBlockType(block.Type)
	if bt == nil {
		return nil, errors.New("unknown block type: " + block.Type)
	}
	if err := bt.ValidateState(state); err != nil {
		return nil, err
	}

	block.State = types.JSON(state)
	return &block, ctx.db.Save(&block).Error
}
application_context.MahresourcesContext.DeleteBlock method · go · L146-L169 (24 LOC)
application_context/block_context.go
func (ctx *MahresourcesContext) DeleteBlock(blockID uint) error {
	var block models.NoteBlock
	if err := ctx.db.First(&block, blockID).Error; err != nil {
		return err
	}

	noteID := block.NoteID
	isText := block.Type == "text"

	// Use transaction to ensure atomicity of deletion and description sync
	return ctx.db.Transaction(func(tx *gorm.DB) error {
		if err := tx.Delete(&block).Error; err != nil {
			return err
		}

		// Sync first text block to note description within the same transaction
		if isText {
			if err := syncFirstTextBlockToDescriptionTx(tx, noteID); err != nil {
				log.Printf("Warning: failed to sync description for note %d: %v", noteID, err)
			}
		}
		return nil
	})
}
application_context.MahresourcesContext.ReorderBlocks method · go · L172-L201 (30 LOC)
application_context/block_context.go
func (ctx *MahresourcesContext) ReorderBlocks(noteID uint, positions map[uint]string) error {
	if len(positions) == 0 {
		return nil
	}

	// Collect block IDs for validation
	blockIDs := make([]uint, 0, len(positions))
	for blockID := range positions {
		blockIDs = append(blockIDs, blockID)
	}

	// Verify all blocks belong to the specified note
	var count int64
	if err := ctx.db.Model(&models.NoteBlock{}).Where("id IN ? AND note_id = ?", blockIDs, noteID).Count(&count).Error; err != nil {
		return err
	}
	if int(count) != len(positions) {
		return errors.New("one or more block IDs do not belong to the specified note")
	}

	return ctx.db.Transaction(func(tx *gorm.DB) error {
		for blockID, position := range positions {
			if err := tx.Model(&models.NoteBlock{}).Where("id = ? AND note_id = ?", blockID, noteID).
				Update("position", position).Error; err != nil {
				return err
			}
		}
		return nil
	})
}
application_context.syncFirstTextBlockToDescriptionTx function · go · L205-L224 (20 LOC)
application_context/block_context.go
func syncFirstTextBlockToDescriptionTx(tx *gorm.DB, noteID uint) error {
	var blocks []models.NoteBlock
	if err := tx.Where("note_id = ? AND type = ?", noteID, "text").
		Order("position ASC").Limit(1).Find(&blocks).Error; err != nil {
		return err
	}

	if len(blocks) == 0 {
		return nil
	}

	var content struct {
		Text string `json:"text"`
	}
	if err := json.Unmarshal(blocks[0].Content, &content); err != nil {
		return err
	}

	return tx.Model(&models.Note{}).Where("id = ?", noteID).Update("description", content.Text).Error
}
Same scanner, your repo: https://repobility.com — Repobility
application_context.MahresourcesContext.RebalanceBlockPositions method · go · L229-L251 (23 LOC)
application_context/block_context.go
func (ctx *MahresourcesContext) RebalanceBlockPositions(noteID uint) error {
	var blocks []models.NoteBlock
	if err := ctx.db.Where("note_id = ?", noteID).Order("position ASC").Find(&blocks).Error; err != nil {
		return err
	}

	if len(blocks) == 0 {
		return nil
	}

	// Generate evenly distributed positions
	newPositions := lib.GenerateEvenPositions(len(blocks))

	return ctx.db.Transaction(func(tx *gorm.DB) error {
		for i, block := range blocks {
			if err := tx.Model(&models.NoteBlock{}).Where("id = ?", block.ID).
				Update("position", newPositions[i]).Error; err != nil {
				return err
			}
		}
		return nil
	})
}
application_context.MahresourcesContext.UpdateBlockStateFromRequest method · go · L256-L264 (9 LOC)
application_context/block_context.go
func (ctx *MahresourcesContext) UpdateBlockStateFromRequest(blockId uint, r *http.Request) error {
	var stateUpdate json.RawMessage
	if err := json.NewDecoder(r.Body).Decode(&stateUpdate); err != nil {
		return err
	}

	_, err := ctx.UpdateBlockState(blockId, stateUpdate)
	return err
}
application_context.MahresourcesContext.GetCalendarEvents method · go · L286-L406 (121 LOC)
application_context/block_context.go
func (ctx *MahresourcesContext) GetCalendarEvents(blockID uint, start, end time.Time) (*interfaces.CalendarEventsResponse, error) {
	// Get the block
	block, err := ctx.GetBlock(blockID)
	if err != nil {
		return nil, err
	}

	// Verify block type
	if block.Type != "calendar" {
		return nil, errors.New("block is not a calendar type")
	}

	// Parse block content to get calendar sources
	var content struct {
		Calendars []block_types.CalendarSource `json:"calendars"`
	}
	if err := json.Unmarshal(block.Content, &content); err != nil {
		return nil, fmt.Errorf("failed to parse block content: %w", err)
	}

	var allEvents []interfaces.CalendarEvent
	var calendars []interfaces.CalendarInfo
	var calendarErrors []interfaces.CalendarError
	var cachedAt time.Time

	// Fetch events from each calendar source
	for _, cal := range content.Calendars {
		var icsContent []byte
		var fetchTime time.Time
		var fetchErr error

		switch cal.Source.Type {
		case "url":
			icsContent, fetchTime, fetchErr = ct
application_context.MahresourcesContext.fetchICSFromURL method · go · L410-L434 (25 LOC)
application_context/block_context.go
func (ctx *MahresourcesContext) fetchICSFromURL(url string) ([]byte, time.Time, error) {
	// Get configured TTL or default
	cacheTTL := ctx.Config.ICSCacheTTL
	if cacheTTL == 0 {
		cacheTTL = 30 * time.Minute
	}

	// Check cache first
	if entry, ok := ctx.icsCache.Get(url); ok {
		if entry.IsFresh(cacheTTL) {
			return entry.Content, entry.FetchedAt, nil
		}
		// Entry exists but is stale - try conditional fetch
		content, fetchTime, err := ctx.fetchAndCacheICS(url, entry)
		if err != nil {
			// If conditional fetch fails, return stale data
			log.Printf("Conditional fetch failed for %s, using cached data: %v", url, err)
			return entry.Content, entry.FetchedAt, nil
		}
		return content, fetchTime, nil
	}

	// No cache entry - fetch fresh
	return ctx.fetchAndCacheICS(url, nil)
}
application_context.MahresourcesContext.fetchAndCacheICS method · go · L437-L496 (60 LOC)
application_context/block_context.go
func (ctx *MahresourcesContext) fetchAndCacheICS(url string, existingEntry *ICSCacheEntry) ([]byte, time.Time, error) {
	req, err := http.NewRequest(http.MethodGet, url, nil)
	if err != nil {
		return nil, time.Time{}, fmt.Errorf("failed to create request: %w", err)
	}

	// Add conditional headers if we have a previous entry
	if existingEntry != nil {
		if existingEntry.ETag != "" {
			req.Header.Set("If-None-Match", existingEntry.ETag)
		}
		if existingEntry.LastModified != "" {
			req.Header.Set("If-Modified-Since", existingEntry.LastModified)
		}
	}

	// Use configured timeouts
	client := &http.Client{
		Timeout: ctx.Config.RemoteResourceConnectTimeout,
	}
	if client.Timeout == 0 {
		client.Timeout = 30 * time.Second
	}

	resp, err := client.Do(req)
	if err != nil {
		return nil, time.Time{}, fmt.Errorf("failed to fetch URL: %w", err)
	}
	defer resp.Body.Close()

	// Handle 304 Not Modified
	if resp.StatusCode == http.StatusNotModified && existingEntry != nil {
		// Refresh the cach
application_context.MahresourcesContext.fetchICSFromResource method · go · L500-L533 (34 LOC)
application_context/block_context.go
func (ctx *MahresourcesContext) fetchICSFromResource(resourceID uint) ([]byte, time.Time, error) {
	resource, err := ctx.GetResource(resourceID)
	if err != nil {
		return nil, time.Time{}, fmt.Errorf("failed to get resource: %w", err)
	}

	// Determine which filesystem to use
	var fs = ctx.fs
	if resource.StorageLocation != nil && *resource.StorageLocation != "" {
		if altFs, ok := ctx.altFileSystems[*resource.StorageLocation]; ok {
			fs = altFs
		}
	}

	// Open and read the file with size limit (consistent with URL fetch)
	f, err := fs.Open(resource.GetCleanLocation())
	if err != nil {
		return nil, time.Time{}, fmt.Errorf("failed to open resource file: %w", err)
	}
	defer f.Close()

	content, err := io.ReadAll(io.LimitReader(f, maxICSFileSize+1))
	if err != nil {
		return nil, time.Time{}, fmt.Errorf("failed to read resource file: %w", err)
	}

	// Check if we exceeded the size limit
	if int64(len(content)) > maxICSFileSize {
		return nil, time.Time{}, fmt.Errorf("ICS resource file 
application_context.MahresourcesContext.parseCustomEventsFromState method · go · L537-L579 (43 LOC)
application_context/block_context.go
func (ctx *MahresourcesContext) parseCustomEventsFromState(stateJSON []byte, start, end time.Time) ([]interfaces.CalendarEvent, bool) {
	var state struct {
		CustomEvents []block_types.CustomCalendarEvent `json:"customEvents"`
	}
	if err := json.Unmarshal(stateJSON, &state); err != nil {
		log.Printf("Failed to parse custom events from state: %v", err)
		return nil, false
	}

	if len(state.CustomEvents) == 0 {
		return nil, false
	}

	var filtered []interfaces.CalendarEvent
	for _, ce := range state.CustomEvents {
		eventStart, err := time.Parse(time.RFC3339, ce.Start)
		if err != nil {
			log.Printf("Custom event %s: failed to parse start time: %v", ce.ID, err)
			continue
		}
		eventEnd, err := time.Parse(time.RFC3339, ce.End)
		if err != nil {
			log.Printf("Custom event %s: failed to parse end time: %v", ce.ID, err)
			continue
		}

		// Filter to date range (same logic as ICS events)
		if eventStart.Before(end) && eventEnd.After(start) {
			filtered = append(filtered, interfaces.C
application_context.NewICSCache function · go · L41-L48 (8 LOC)
application_context/calendar_cache.go
func NewICSCache(maxEntries int, ttl time.Duration) *ICSCache {
	return &ICSCache{
		entries:    make(map[string]*list.Element),
		order:      list.New(),
		maxEntries: maxEntries,
		ttl:        ttl,
	}
}
Repobility · code-quality intelligence platform · https://repobility.com
application_context.ICSCache.Get method · go · L53-L67 (15 LOC)
application_context/calendar_cache.go
func (c *ICSCache) Get(url string) (*ICSCacheEntry, bool) {
	c.mu.Lock()
	defer c.mu.Unlock()

	elem, ok := c.entries[url]
	if !ok {
		return nil, false
	}

	// Move to front (most recently used)
	c.order.MoveToFront(elem)

	item := elem.Value.(*icsCacheItem)
	return item.entry, true
}
application_context.ICSCache.Set method · go · L70-L98 (29 LOC)
application_context/calendar_cache.go
func (c *ICSCache) Set(url string, content []byte, etag, lastModified string) {
	c.mu.Lock()
	defer c.mu.Unlock()

	entry := &ICSCacheEntry{
		Content:      content,
		FetchedAt:    time.Now(),
		ETag:         etag,
		LastModified: lastModified,
	}

	// Check if URL already exists
	if elem, ok := c.entries[url]; ok {
		// Update existing entry
		c.order.MoveToFront(elem)
		elem.Value.(*icsCacheItem).entry = entry
		return
	}

	// Evict oldest entries if at capacity
	for c.order.Len() >= c.maxEntries {
		c.evictOldest()
	}

	// Add new entry
	item := &icsCacheItem{url: url, entry: entry}
	elem := c.order.PushFront(item)
	c.entries[url] = elem
}
application_context.ICSCache.evictOldest method · go · L101-L108 (8 LOC)
application_context/calendar_cache.go
func (c *ICSCache) evictOldest() {
	elem := c.order.Back()
	if elem != nil {
		item := elem.Value.(*icsCacheItem)
		delete(c.entries, item.url)
		c.order.Remove(elem)
	}
}
application_context.ICSCache.Clear method · go · L118-L124 (7 LOC)
application_context/calendar_cache.go
func (c *ICSCache) Clear() {
	c.mu.Lock()
	defer c.mu.Unlock()

	c.entries = make(map[string]*list.Element)
	c.order.Init()
}
application_context.ParseICSEvents function · go · L129-L156 (28 LOC)
application_context/calendar_cache.go
func ParseICSEvents(content []byte, calendarID string, rangeStart, rangeEnd time.Time) ([]interfaces.CalendarEvent, error) {
	cal, err := ics.ParseCalendar(strings.NewReader(string(content)))
	if err != nil {
		return nil, err
	}

	var events []interfaces.CalendarEvent

	for _, component := range cal.Components {
		event, ok := component.(*ics.VEvent)
		if !ok {
			continue
		}

		calEvent := parseVEvent(event, calendarID)
		if calEvent == nil {
			continue
		}

		// Filter by date range
		// Include event if it overlaps with the range at all
		if eventOverlapsRange(calEvent.Start, calEvent.End, rangeStart, rangeEnd) {
			events = append(events, *calEvent)
		}
	}

	return events, nil
}
application_context.parseVEvent function · go · L159-L214 (56 LOC)
application_context/calendar_cache.go
func parseVEvent(event *ics.VEvent, calendarID string) *interfaces.CalendarEvent {
	uid := event.GetProperty(ics.ComponentPropertyUniqueId)
	if uid == nil {
		return nil
	}

	summary := event.GetProperty(ics.ComponentPropertySummary)
	dtstart := event.GetProperty(ics.ComponentPropertyDtStart)
	dtend := event.GetProperty(ics.ComponentPropertyDtEnd)

	if dtstart == nil {
		return nil
	}

	startTime, allDay := parseICSDateTime(dtstart)
	if startTime.IsZero() {
		return nil
	}

	var endTime time.Time
	if dtend != nil {
		endTime, _ = parseICSDateTime(dtend)
	}
	if endTime.IsZero() {
		// Default end time to start time + 1 hour (or +1 day for all-day events)
		if allDay {
			endTime = startTime.Add(24 * time.Hour)
		} else {
			endTime = startTime.Add(time.Hour)
		}
	}

	calEvent := &interfaces.CalendarEvent{
		ID:         uid.Value,
		CalendarID: calendarID,
		Start:      startTime,
		End:        endTime,
		AllDay:     allDay,
	}

	if summary != nil {
		calEvent.Title = summary.Value
	}

	
application_context.parseICSDateTime function · go · L217-L270 (54 LOC)
application_context/calendar_cache.go
func parseICSDateTime(prop *ics.IANAProperty) (time.Time, bool) {
	if prop == nil {
		return time.Time{}, false
	}

	value := prop.Value
	params := prop.ICalParameters

	// Check if it's a date-only value (all-day event)
	isAllDay := false
	if valueParam, ok := params["VALUE"]; ok && len(valueParam) > 0 {
		isAllDay = valueParam[0] == "DATE"
	}

	// Check for timezone
	var loc *time.Location = time.UTC
	if tzid, ok := params["TZID"]; ok && len(tzid) > 0 {
		if parsedLoc, err := time.LoadLocation(tzid[0]); err == nil {
			loc = parsedLoc
		}
	}

	// Try parsing various formats
	if isAllDay {
		// DATE format: YYYYMMDD
		t, err := time.ParseInLocation("20060102", value, loc)
		if err == nil {
			return t.UTC(), true
		}
	}

	// Check if it ends with Z (UTC)
	if strings.HasSuffix(value, "Z") {
		// DATETIME format with Z: YYYYMMDDTHHMMSSz
		t, err := time.Parse("20060102T150405Z", value)
		if err == nil {
			return t.UTC(), false
		}
	}

	// DATETIME format without Z: YYYYMMDDTHHMMSS
	t, 
application_context.MahresourcesContext.GetCategories method · go · L18-L23 (6 LOC)
application_context/category_context.go
func (ctx *MahresourcesContext) GetCategories(offset, maxResults int, query *query_models.CategoryQuery) ([]models.Category, error) {
	var categories []models.Category
	scope := database_scopes.CategoryQuery(query)

	return categories, ctx.db.Scopes(scope).Limit(maxResults).Offset(offset).Find(&categories).Error
}
Repobility · severity-and-effort ranking · https://repobility.com
application_context.MahresourcesContext.GetCategoriesCount method · go · L25-L30 (6 LOC)
application_context/category_context.go
func (ctx *MahresourcesContext) GetCategoriesCount(query *query_models.CategoryQuery) (int64, error) {
	var category models.Category
	var count int64

	return count, ctx.db.Scopes(database_scopes.CategoryQuery(query)).Model(&category).Count(&count).Error
}
application_context.MahresourcesContext.GetCategoriesWithIds method · go · L32-L46 (15 LOC)
application_context/category_context.go
func (ctx *MahresourcesContext) GetCategoriesWithIds(ids *[]uint, limit int) ([]models.Category, error) {
	var categories []models.Category

	if len(*ids) == 0 {
		return categories, nil
	}

	query := ctx.db

	if limit > 0 {
		query = query.Limit(limit)
	}

	return categories, query.Find(&categories, *ids).Error
}
application_context.MahresourcesContext.CreateCategory method · go · L48-L71 (24 LOC)
application_context/category_context.go
func (ctx *MahresourcesContext) CreateCategory(categoryQuery *query_models.CategoryCreator) (*models.Category, error) {
	if strings.TrimSpace(categoryQuery.Name) == "" {
		return nil, errors.New("category name must be non-empty")
	}

	category := models.Category{
		Name:          categoryQuery.Name,
		Description:   categoryQuery.Description,
		CustomHeader:  categoryQuery.CustomHeader,
		CustomSidebar: categoryQuery.CustomSidebar,
		CustomSummary: categoryQuery.CustomSummary,
		CustomAvatar:  categoryQuery.CustomAvatar,
		MetaSchema:    categoryQuery.MetaSchema,
	}

	if err := ctx.db.Create(&category).Error; err != nil {
		return nil, err
	}

	ctx.Logger().Info(models.LogActionCreate, "category", &category.ID, category.Name, "Created category", nil)

	ctx.InvalidateSearchCacheByType(EntityTypeCategory)
	return &category, nil
}
application_context.MahresourcesContext.UpdateCategory method · go · L73-L97 (25 LOC)
application_context/category_context.go
func (ctx *MahresourcesContext) UpdateCategory(categoryQuery *query_models.CategoryEditor) (*models.Category, error) {
	var category models.Category
	if err := ctx.db.First(&category, categoryQuery.ID).Error; err != nil {
		return nil, err
	}

	if strings.TrimSpace(categoryQuery.Name) != "" {
		category.Name = categoryQuery.Name
	}
	category.Description = categoryQuery.Description
	category.CustomHeader = categoryQuery.CustomHeader
	category.CustomSidebar = categoryQuery.CustomSidebar
	category.CustomSummary = categoryQuery.CustomSummary
	category.CustomAvatar = categoryQuery.CustomAvatar
	category.MetaSchema = categoryQuery.MetaSchema

	if err := ctx.db.Save(&category).Error; err != nil {
		return nil, err
	}

	ctx.Logger().Info(models.LogActionUpdate, "category", &category.ID, category.Name, "Updated category", nil)

	ctx.InvalidateSearchCacheByType(EntityTypeCategory)
	return &category, nil
}
application_context.MahresourcesContext.DeleteCategory method · go · L99-L113 (15 LOC)
application_context/category_context.go
func (ctx *MahresourcesContext) DeleteCategory(categoryId uint) error {
	// Load category name before deletion for audit log
	var category models.Category
	if err := ctx.db.First(&category, categoryId).Error; err != nil {
		return err
	}
	categoryName := category.Name

	err := ctx.db.Select(clause.Associations).Delete(&category).Error
	if err == nil {
		ctx.Logger().Info(models.LogActionDelete, "category", &categoryId, categoryName, "Deleted category", nil)
		ctx.InvalidateSearchCacheByType(EntityTypeCategory)
	}
	return err
}
application_context.NewMahresourcesContext function · go · L138-L194 (57 LOC)
application_context/context.go
func NewMahresourcesContext(filesystem afero.Fs, db *gorm.DB, readOnlyDB *sqlx.DB, config *MahresourcesConfig) *MahresourcesContext {
	altFileSystems := make(map[string]afero.Fs, len(config.AltFileSystems))

	for key, path := range config.AltFileSystems {
		altFileSystems[key] = storage.CreateStorage(path)
	}

	thumbnailGenerationLock := lib.NewIDLock[uint](uint(0), nil)
	videoThumbConcurrency := config.VideoThumbnailConcurrency
	if videoThumbConcurrency == 0 {
		videoThumbConcurrency = 4
	}
	videoThumbnailGenerationLock := lib.NewIDLock[uint](videoThumbConcurrency, nil)
	officeDocumentGenerationLock := lib.NewIDLock[uint](uint(2), nil)
	resourceHashLock := lib.NewIDLock[string](uint(0), nil)
	versionUploadLock := lib.NewIDLock[uint](uint(0), nil)

	// Initialize search cache with 60 second TTL and 1000 max entries
	searchCache := NewSearchCache(60*time.Second, 1000)

	// Initialize ICS cache with configurable or default values
	icsCacheMaxEntries := config.ICSCacheMaxEntries
	if icsCa
application_context.MahresourcesContext.WithRequest method · go · L209-L214 (6 LOC)
application_context/context.go
func (ctx *MahresourcesContext) WithRequest(r *http.Request) any {
	// Create a shallow copy to avoid modifying the original
	ctxCopy := *ctx
	ctxCopy.currentRequest = r
	return &ctxCopy
}
application_context.MahresourcesContext.QueueForHashing method · go · L223-L233 (11 LOC)
application_context/context.go
func (ctx *MahresourcesContext) QueueForHashing(resourceID uint) bool {
	if ctx.hashQueue == nil {
		return false
	}
	select {
	case ctx.hashQueue <- resourceID:
		return true
	default:
		return false
	}
}
Repobility's GitHub App fixes findings like these · https://github.com/apps/repobility-bot
application_context.MahresourcesContext.QueueForThumbnailing method · go · L242-L252 (11 LOC)
application_context/context.go
func (ctx *MahresourcesContext) QueueForThumbnailing(resourceID uint) bool {
	if ctx.thumbnailQueue == nil {
		return false
	}
	select {
	case ctx.thumbnailQueue <- resourceID:
		return true
	default:
		return false
	}
}
application_context.MahresourcesContext.OnResourceFileChanged method · go · L256-L261 (6 LOC)
application_context/context.go
func (ctx *MahresourcesContext) OnResourceFileChanged(resourceID uint) {
	// Delete old hash - cascade will remove associated similarity pairs
	ctx.db.Where("resource_id = ?", resourceID).Delete(&models.ImageHash{})
	// Re-queue for hashing
	ctx.QueueForHashing(resourceID)
}
application_context.MahresourcesContext.EnsureForeignKeysActive method · go · L265-L282 (18 LOC)
application_context/context.go
func (ctx *MahresourcesContext) EnsureForeignKeysActive(db *gorm.DB) {
	if ctx.Config.DbType != constants.DbTypeSqlite {
		return
	}

	query := "PRAGMA foreign_keys = ON;"

	if db == nil {
		if err := ctx.db.Exec(query).Error; err != nil {
			log.Printf("warning: failed to enable foreign keys: %v", err)
		}
		return
	}

	if err := db.Exec(query).Error; err != nil {
		log.Printf("warning: failed to enable foreign keys: %v", err)
	}
}
application_context.MahresourcesContext.IsReadOnlyDBEnforced method · go · L286-L298 (13 LOC)
application_context/context.go
func (ctx *MahresourcesContext) IsReadOnlyDBEnforced() bool {
	if ctx.readOnlyDB == nil {
		return false
	}
	dsn := ctx.Config.DbReadOnlyDsn
	if strings.Contains(dsn, "mode=ro") {
		return true
	}
	if ctx.Config.DbType == constants.DbTypePosgres && dsn != "" && dsn != ctx.Config.DbDsn {
		return true
	}
	return false
}
application_context.MahresourcesContext.WithTransaction method · go · L300-L308 (9 LOC)
application_context/context.go
func (ctx *MahresourcesContext) WithTransaction(txFn func(transactionCtx *MahresourcesContext) error) error {
	return ctx.db.Transaction(func(tx *gorm.DB) error {
		// Create a shallow copy that shares the parent's locks, caches, and alt filesystems
		// but uses the transactional *gorm.DB
		txCtx := *ctx
		txCtx.db = tx
		return txFn(&txCtx)
	})
}
application_context.timeOrNil function · go · L314-L322 (9 LOC)
application_context/context.go
func timeOrNil(time time.Time, err error) *time.Time {
	if err != nil {
		log.Printf("couldn't parse date: %v", err)

		return nil
	}

	return &time
}
application_context.metaKeys function · go · L334-L358 (25 LOC)
application_context/context.go
func metaKeys(ctx *MahresourcesContext, table string) ([]interfaces.MetaKey, error) {
	var results []interfaces.MetaKey

	if ctx.Config.DbType == constants.DbTypePosgres {
		if err := ctx.db.
			Table(table).
			Select("DISTINCT jsonb_object_keys(Meta) as Key").
			Where("Meta IS NOT NULL").
			Scan(&results).Error; err != nil {
			return nil, err
		}
	} else if ctx.Config.DbType == constants.DbTypeSqlite {
		if err := ctx.db.
			Table(fmt.Sprintf("%v, json_each(%v.meta)", table, table)).
			Select("DISTINCT json_each.key as Key").
			Where("Meta IS NOT NULL").
			Scan(&results).Error; err != nil {
			return nil, err
		}
	} else {
		results = make([]interfaces.MetaKey, 0)
	}

	return results, nil
}
application_context.copySeedDatabase function · go · L361-L379 (19 LOC)
application_context/context.go
func copySeedDatabase(src, dst string) error {
	srcFile, err := os.Open(src)
	if err != nil {
		return fmt.Errorf("failed to open seed database %s: %w", src, err)
	}
	defer srcFile.Close()

	dstFile, err := os.Create(dst)
	if err != nil {
		return fmt.Errorf("failed to create destination database %s: %w", dst, err)
	}
	defer dstFile.Close()

	if _, err := io.Copy(dstFile, srcFile); err != nil {
		return fmt.Errorf("failed to copy database: %w", err)
	}

	return dstFile.Sync()
}
Same scanner, your repo: https://repobility.com — Repobility
application_context.CreateContextWithConfig function · go · L383-L546 (164 LOC)
application_context/context.go
func CreateContextWithConfig(cfg *MahresourcesInputConfig) (*MahresourcesContext, *gorm.DB, afero.Fs) {
	var db *gorm.DB
	var mainFs afero.Fs

	// Determine effective database settings
	dbType := cfg.DbType
	dbDsn := cfg.DbDsn
	readOnlyDsn := cfg.DbReadOnlyDsn

	// Validate seed-db usage
	if cfg.SeedDB != "" {
		if !cfg.MemoryDB {
			log.Fatal("-seed-db requires -memory-db or -ephemeral flag")
		}
		if strings.ToUpper(cfg.DbType) == "POSTGRES" {
			log.Fatal("-seed-db is only supported with SQLite, not Postgres")
		}
		// Check seed-db file exists
		if info, err := os.Stat(cfg.SeedDB); err != nil {
			if os.IsNotExist(err) {
				log.Fatalf("-seed-db file does not exist: %s", cfg.SeedDB)
			}
			log.Fatalf("-seed-db file error: %v", err)
		} else if info.IsDir() {
			log.Fatalf("-seed-db path is a directory, not a file: %s", cfg.SeedDB)
		}
	}

	if cfg.MemoryDB {
		dbType = "SQLITE"
		// Use a temp file with WAL mode for better concurrent write handling
		// The file is auto-deleted whe
application_context.CreateContext function · go · L550-L572 (23 LOC)
application_context/context.go
func CreateContext() (*MahresourcesContext, *gorm.DB, afero.Fs) {
	var numAlt int64 = 0

	if fileAltCount, err := strconv.ParseInt(os.Getenv("FILE_ALT_COUNT"), 10, 8); err == nil {
		numAlt = fileAltCount
	}

	altFSystems := make(map[string]string, numAlt)
	for i := int64(0); i < numAlt; i++ {
		altFSystems[os.Getenv(fmt.Sprintf("FILE_ALT_NAME_%v", i+1))] = os.Getenv(fmt.Sprintf("FILE_ALT_PATH_%v", i+1))
	}

	return CreateContextWithConfig(&MahresourcesInputConfig{
		FileSavePath:   os.Getenv("FILE_SAVE_PATH"),
		DbType:         os.Getenv("DB_TYPE"),
		DbDsn:          os.Getenv("DB_DSN"),
		DbReadOnlyDsn:  os.Getenv("DB_READONLY_DSN"),
		DbLogFile:      os.Getenv("DB_LOG_FILE"),
		BindAddress:    os.Getenv("BIND_ADDRESS"),
		FfmpegPath:     os.Getenv("FFMPEG_PATH"),
		AltFileSystems: altFSystems,
	})
}
application_context.MahresourcesContext.TagCRUD method · go · L26-L43 (18 LOC)
application_context/crud_factories.go
func (ctx *MahresourcesContext) TagCRUD() (
	*CRUDReader[models.Tag, *query_models.TagQuery],
	*CRUDWriter[models.Tag, *query_models.TagCreator],
) {
	reader := NewCRUDReader[models.Tag, *query_models.TagQuery](ctx.db, CRUDReaderConfig[*query_models.TagQuery]{
		ScopeFn:       ScopeWithIgnoreSort(database_scopes.TagQuery),
		ScopeFnNoSort: ScopeWithIgnoreSortForCount(database_scopes.TagQuery),
		PreloadAssoc:  true,
	})

	writer := NewCRUDWriter[models.Tag, *query_models.TagCreator](
		ctx.db,
		buildTag,
		"tag",
	)

	return reader, writer
}
application_context.buildTag function · go · L45-L54 (10 LOC)
application_context/crud_factories.go
func buildTag(creator *query_models.TagCreator) (models.Tag, error) {
	if strings.TrimSpace(creator.Name) == "" {
		return models.Tag{}, errors.New("tag name must be non-empty")
	}
	return models.Tag{
		ID:          creator.ID,
		Name:        creator.Name,
		Description: creator.Description,
	}, nil
}
application_context.MahresourcesContext.CategoryCRUD method · go · L57-L73 (17 LOC)
application_context/crud_factories.go
func (ctx *MahresourcesContext) CategoryCRUD() (
	*CRUDReader[models.Category, *query_models.CategoryQuery],
	*CRUDWriter[models.Category, *query_models.CategoryCreator],
) {
	reader := NewCRUDReader[models.Category, *query_models.CategoryQuery](ctx.db, CRUDReaderConfig[*query_models.CategoryQuery]{
		ScopeFn:      database_scopes.CategoryQuery,
		PreloadAssoc: true,
	})

	writer := NewCRUDWriter[models.Category, *query_models.CategoryCreator](
		ctx.db,
		buildCategory,
		"category",
	)

	return reader, writer
}
application_context.buildCategory function · go · L75-L88 (14 LOC)
application_context/crud_factories.go
func buildCategory(creator *query_models.CategoryCreator) (models.Category, error) {
	if strings.TrimSpace(creator.Name) == "" {
		return models.Category{}, errors.New("category name must be non-empty")
	}
	return models.Category{
		Name:          creator.Name,
		Description:   creator.Description,
		CustomHeader:  creator.CustomHeader,
		CustomSidebar: creator.CustomSidebar,
		CustomSummary: creator.CustomSummary,
		CustomAvatar:  creator.CustomAvatar,
		MetaSchema:    creator.MetaSchema,
	}, nil
}
application_context.MahresourcesContext.ResourceCategoryCRUD method · go · L91-L107 (17 LOC)
application_context/crud_factories.go
func (ctx *MahresourcesContext) ResourceCategoryCRUD() (
	*CRUDReader[models.ResourceCategory, *query_models.ResourceCategoryQuery],
	*CRUDWriter[models.ResourceCategory, *query_models.ResourceCategoryCreator],
) {
	reader := NewCRUDReader[models.ResourceCategory, *query_models.ResourceCategoryQuery](ctx.db, CRUDReaderConfig[*query_models.ResourceCategoryQuery]{
		ScopeFn:      database_scopes.ResourceCategoryQuery,
		PreloadAssoc: true,
	})

	writer := NewCRUDWriter[models.ResourceCategory, *query_models.ResourceCategoryCreator](
		ctx.db,
		buildResourceCategory,
		"resourceCategory",
	)

	return reader, writer
}
application_context.buildResourceCategory function · go · L109-L122 (14 LOC)
application_context/crud_factories.go
func buildResourceCategory(creator *query_models.ResourceCategoryCreator) (models.ResourceCategory, error) {
	if strings.TrimSpace(creator.Name) == "" {
		return models.ResourceCategory{}, errors.New("resource category name must be non-empty")
	}
	return models.ResourceCategory{
		Name:          creator.Name,
		Description:   creator.Description,
		CustomHeader:  creator.CustomHeader,
		CustomSidebar: creator.CustomSidebar,
		CustomSummary: creator.CustomSummary,
		CustomAvatar:  creator.CustomAvatar,
		MetaSchema:    creator.MetaSchema,
	}, nil
}
Repobility · code-quality intelligence platform · https://repobility.com
application_context.MahresourcesContext.QueryCRUD method · go · L125-L141 (17 LOC)
application_context/crud_factories.go
func (ctx *MahresourcesContext) QueryCRUD() (
	*CRUDReader[models.Query, *query_models.QueryQuery],
	*CRUDWriter[models.Query, *query_models.QueryCreator],
) {
	reader := NewCRUDReader[models.Query, *query_models.QueryQuery](ctx.db, CRUDReaderConfig[*query_models.QueryQuery]{
		ScopeFn:      database_scopes.QueryQuery,
		PreloadAssoc: false, // Query model doesn't have associations to preload
	})

	writer := NewCRUDWriter[models.Query, *query_models.QueryCreator](
		ctx.db,
		buildQuery,
		"query",
	)

	return reader, writer
}
application_context.buildQuery function · go · L143-L152 (10 LOC)
application_context/crud_factories.go
func buildQuery(creator *query_models.QueryCreator) (models.Query, error) {
	if strings.TrimSpace(creator.Name) == "" {
		return models.Query{}, errors.New("query name must be non-empty")
	}
	return models.Query{
		Name:     creator.Name,
		Text:     creator.Text,
		Template: creator.Template,
	}, nil
}
application_context.MahresourcesContext.NoteTypeCRUD method · go · L155-L171 (17 LOC)
application_context/crud_factories.go
func (ctx *MahresourcesContext) NoteTypeCRUD() (
	*CRUDReader[models.NoteType, *query_models.NoteTypeQuery],
	*CRUDWriter[models.NoteType, *query_models.NoteTypeEditor],
) {
	reader := NewCRUDReader[models.NoteType, *query_models.NoteTypeQuery](ctx.db, CRUDReaderConfig[*query_models.NoteTypeQuery]{
		ScopeFn:      database_scopes.NoteTypeQuery,
		PreloadAssoc: true,
	})

	writer := NewCRUDWriter[models.NoteType, *query_models.NoteTypeEditor](
		ctx.db,
		buildNoteType,
		"noteType",
	)

	return reader, writer
}
page 1 / 16next ›