This commit is contained in:
2025-09-13 17:40:18 +02:00
parent f539c10c02
commit d90cac4c89
5 changed files with 82 additions and 441 deletions

View File

@@ -1,62 +0,0 @@
module heromodels
import freeflowuniverse.herolib.data.ourtime
import time
// Calendar represents a collection of events
@[heap]
pub struct Calendar {
Base
pub mut:
events []u32 // IDs of calendar events (changed to u32 to match CalendarEvent)
color string // Hex color code
timezone string
is_public bool
}
@[params]
pub struct CalendarArgs {
BaseArgs
pub mut:
events []u32
color string
timezone string
is_public bool
}
pub fn calendar_new(args CalendarArgs) !Calendar {
mut commentids:=[]u32{}
mut obj := Calendar{
id: args.id or {0} // Will be set by DB?
name: args.name
description: args.description
created_at: ourtime.now().unix()
updated_at: ourtime.now().unix()
securitypolicy: args.securitypolicy or {0}
tags: tags2id(args.tags)!
comments: comments2ids(args.comments)!
group_id: args.group_id
events: args.events
color: args.color
timezone: args.timezone
is_public: args.is_public
}
return obj
}
pub fn (mut c Calendar) add_event(event_id u32) { // Changed event_id to u32
if event_id !in c.events {
c.events << event_id
c.updated_at = ourtime.now().unix() // Use Base's updated_at
}
}
pub fn (mut c Calendar) dump() []u8 {
// TODO: implement based on lib/data/encoder/readme.md
return []u8{}
}
pub fn calendar_load(data []u8) Calendar {
// TODO: implement based on lib/data/encoder/readme.md
return Calendar{}
}

View File

@@ -1,261 +0,0 @@
module heromodels
import crypto.blake3
import json
import freeflowuniverse.herolib.data.ourtime
import freeflowuniverse.herolib.data.encoder
import freeflowuniverse.herolib.core.redisclient
// CalendarEvent represents a single event in a calendar
@[heap]
pub struct CalendarEvent {
Base
pub mut:
title string
start_time i64 // Unix timestamp
end_time i64 // Unix timestamp
location string
attendees []u32 // IDs of user groups
fs_items []u32 // IDs of linked files or dirs
calendar_id u32 // Associated calendar
status EventStatus
is_all_day bool
is_recurring bool
recurrence []RecurrenceRule // normally empty
reminder_mins []int // Minutes before event for reminders
color string // Hex color code
timezone string
}
pub struct Attendee {
pub mut:
user_id u32
status AttendanceStatus
role AttendeeRole
}
pub enum AttendanceStatus {
no_response
accepted
declined
tentative
}
pub enum AttendeeRole {
required
optional
organizer
}
pub enum EventStatus {
draft
published
cancelled
completed
}
pub struct RecurrenceRule {
pub mut:
frequency RecurrenceFreq
interval int // Every N frequencies
until i64 // End date (Unix timestamp)
count int // Number of occurrences
by_weekday []int // Days of week (0=Sunday)
by_monthday []int // Days of month
}
pub enum RecurrenceFreq {
none
daily
weekly
monthly
yearly
}
@[params]
pub struct CalendarEventArgs {
BaseArgs
pub mut:
title string
start_time string // use ourtime module to go from string to epoch
end_time string // use ourtime module to go from string to epoch
location string
attendees []u32 // IDs of user groups
fs_items []u32 // IDs of linked files or dirs
calendar_id u32 // Associated calendar
status EventStatus
is_all_day bool
is_recurring bool
recurrence []RecurrenceRule
reminder_mins []int // Minutes before event for reminders
color string // Hex color code
timezone string
}
pub fn calendar_event_new(args CalendarEventArgs) !CalendarEvent {
// Convert tags to u32 ID
tags_id := tags2id(args.tags)!
return CalendarEvent{
// Base fields
id: args.id or { 0 }
name: args.name
description: args.description
created_at: ourtime.now().unix()
updated_at: ourtime.now().unix()
securitypolicy: args.securitypolicy or { 0 }
tags: tags_id
comments: comments2ids(args.comments)!
// CalendarEvent specific fields
title: args.title
start_time: ourtime.new(args.start_time)!.unix()
end_time: ourtime.new(args.end_time)!.unix()
location: args.location
attendees: args.attendees
fs_items: args.fs_items
calendar_id: args.calendar_id
status: args.status
is_all_day: args.is_all_day
is_recurring: args.is_recurring
recurrence: args.recurrence
reminder_mins: args.reminder_mins
color: args.color
timezone: args.timezone
}
}
pub fn (mut e CalendarEvent) dump() ![]u8 {
// Create a new encoder
mut enc := encoder.new()
// Add version byte
enc.add_u8(1)
// Encode Base fields
enc.add_u32(e.id)
enc.add_string(e.name)
enc.add_string(e.description)
enc.add_i64(e.created_at)
enc.add_i64(e.updated_at)
enc.add_u32(e.securitypolicy)
enc.add_u32(e.tags)
enc.add_list_u32(e.comments)
// Encode CalendarEvent specific fields
enc.add_string(e.title)
enc.add_string(e.description)
enc.add_i64(e.start_time)
enc.add_i64(e.end_time)
enc.add_string(e.location)
enc.add_list_u32(e.attendees)
enc.add_list_u32(e.fs_items)
enc.add_u32(e.calendar_id)
enc.add_u8(u8(e.status))
enc.add_bool(e.is_all_day)
enc.add_bool(e.is_recurring)
// Encode recurrence array
enc.add_u16(u16(e.recurrence.len))
for rule in e.recurrence {
enc.add_u8(u8(rule.frequency))
enc.add_int(rule.interval)
enc.add_i64(rule.until)
enc.add_int(rule.count)
enc.add_list_int(rule.by_weekday)
enc.add_list_int(rule.by_monthday)
}
enc.add_list_int(e.reminder_mins)
enc.add_string(e.color)
enc.add_string(e.timezone)
return enc.data
}
pub fn (ce CalendarEvent) load(data []u8) !CalendarEvent {
// Create a new decoder
mut dec := encoder.decoder_new(data)
// Read version byte
version := dec.get_u8()!
if version != 1 {
return error('wrong version in calendar event load')
}
// Decode Base fields
id := dec.get_u32()!
name := dec.get_string()!
description := dec.get_string()!
created_at := dec.get_i64()!
updated_at := dec.get_i64()!
securitypolicy := dec.get_u32()!
tags := dec.get_u32()!
comments := dec.get_list_u32()!
// Decode CalendarEvent specific fields
title := dec.get_string()!
description2 := dec.get_string()! // Second description field
start_time := dec.get_i64()!
end_time := dec.get_i64()!
location := dec.get_string()!
attendees := dec.get_list_u32()!
fs_items := dec.get_list_u32()!
calendar_id := dec.get_u32()!
status := unsafe { EventStatus(dec.get_u8()!) }
is_all_day := dec.get_bool()!
is_recurring := dec.get_bool()!
// Decode recurrence array
recurrence_len := dec.get_u16()!
mut recurrence := []RecurrenceRule{}
for _ in 0 .. recurrence_len {
frequency := unsafe { RecurrenceFreq(dec.get_u8()!) }
interval := dec.get_int()!
until := dec.get_i64()!
count := dec.get_int()!
by_weekday := dec.get_list_int()!
by_monthday := dec.get_list_int()!
recurrence << RecurrenceRule{
frequency: frequency
interval: interval
until: until
count: count
by_weekday: by_weekday
by_monthday: by_monthday
}
}
reminder_mins := dec.get_list_int()!
color := dec.get_string()!
timezone := dec.get_string()!
return CalendarEvent{
// Base fields
id: id
name: name
description: description
created_at: created_at
updated_at: updated_at
securitypolicy: securitypolicy
tags: tags
comments: comments
// CalendarEvent specific fields
title: title
start_time: start_time
end_time: end_time
location: location
attendees: attendees
fs_items: fs_items
calendar_id: calendar_id
status: status
is_all_day: is_all_day
is_recurring: is_recurring
recurrence: recurrence
reminder_mins: reminder_mins
color: color
timezone: timezone
}
}

View File

@@ -1,117 +0,0 @@
module heromodels
import freeflowuniverse.herolib.data.encoder
import crypto.md5
import freeflowuniverse.herolib.core.redisclient
import freeflowuniverse.herolib.data.ourtime
@[heap]
pub struct Comment {
Base
pub mut:
// id u32
comment string
parent u32 //id of parent comment if any, 0 means none
updated_at i64
author u32 //links to user
}
pub fn (self Comment) type_name() string {
return 'comments'
}
pub fn (self Comment) load(data []u8) !Comment {
return comment_load(data)!
}
pub fn (self Comment) dump() ![]u8{
// Create a new encoder
mut e := encoder.new()
e.add_u8(1)
e.add_u32(self.id)
e.add_string(self.comment)
e.add_u32(self.parent)
e.add_i64(self.updated_at)
e.add_u32(self.author)
return e.data
}
pub fn comment_load(data []u8) !Comment{
// Create a new decoder
mut e := encoder.decoder_new(data)
version := e.get_u8()!
if version != 1 {
panic("wrong version in comment load")
}
mut comment := Comment{}
comment.id = e.get_u32()!
comment.comment = e.get_string()!
comment.parent = e.get_u32()!
comment.updated_at = e.get_i64()!
comment.author = e.get_u32()!
return comment
}
pub struct CommentArg {
pub mut:
comment string
parent u32
author u32
}
pub fn comment_multiset(args []CommentArg) ![]u32 {
return comments2ids(args)!
}
pub fn comments2ids(args []CommentArg) ![]u32 {
return args.map(comment2id(it.comment)!)
}
pub fn comment2id(comment string) !u32 {
comment_fixed := comment.to_lower_ascii().trim_space()
mut redis := redisclient.core_get()!
return if comment_fixed.len > 0{
hash := md5.hexhash(comment_fixed)
comment_found := redis.hget("db:comments", hash)!
if comment_found == ""{
id := u32(redis.incr("db:comments:id")!)
redis.hset("db:comments", hash, id.str())!
redis.hset("db:comments", id.str(), comment_fixed)!
id
}else{
comment_found.u32()
}
} else { 0 }
}
//get new comment, not from the DB
pub fn comment_new(args CommentArg) !Comment{
mut o := Comment {
comment: args.comment
parent: args.parent
updated_at: ourtime.now().unix()
author: args.author
}
return o
}
pub fn comment_set(args CommentArg) !u32{
mut o := comment_new(args)!
// Use openrpcserver set function which now returns the ID
return set[Comment](mut o)!
}
pub fn comment_delete(id u32) ! {
delete[Comment](id)!
}
pub fn comment_exist(id u32) !bool{
return exists[Comment](id)!
}
pub fn comment_get(id u32) !Comment{
return get[Comment](id)!
}

View File

@@ -116,7 +116,7 @@ fn (mut self DBCalendarEvent) load(mut o CalendarEvent, mut e &encoder.Decoder)
o.attendees = e.get_list_u32()!
o.fs_items = e.get_list_u32()!
o.calendar_id = e.get_u32()!
o.status = unsafe { EventStatus(e.get_u8()!) }
o.status = unsafe { EventStatus(e.get_u8()!) } //TODO: is there no better way?
o.is_all_day = e.get_bool()!
o.is_recurring = e.get_bool()!

View File

@@ -0,0 +1,81 @@
module heromodels
import time
import crypto.blake3
import json
// Group represents a collection of users with roles and permissions
@[heap]
pub struct Group {
pub mut:
id string // blake192 hash
name string
description string
members []GroupMember
subgroups []string // IDs of child groups
parent_group string // ID of parent group
created_at i64
updated_at i64
is_public bool
tags []string
}
pub struct GroupMember {
pub mut:
user_id string
role GroupRole
joined_at i64
}
pub enum GroupRole {
reader
writer
admin
owner
}
pub fn (mut g Group) calculate_id() {
content := json.encode(GroupContent{
name: g.name
description: g.description
members: g.members
subgroups: g.subgroups
parent_group: g.parent_group
is_public: g.is_public
tags: g.tags
})
hash := blake3.sum256(content.bytes())
g.id = hash.hex()[..48]
}
struct GroupContent {
name string
description string
members []GroupMember
subgroups []string
parent_group string
is_public bool
tags []string
}
pub fn new_group(name string, description string) Group {
mut group := Group{
name: name
description: description
created_at: time.now().unix()
updated_at: time.now().unix()
is_public: false
}
group.calculate_id()
return group
}
pub fn (mut g Group) add_member(user_id string, role GroupRole) {
g.members << GroupMember{
user_id: user_id
role: role
joined_at: time.now().unix()
}
g.updated_at = time.now().unix()
g.calculate_id()
}