-
Notifications
You must be signed in to change notification settings - Fork 0
Import Migration Guide
Complete documentation for importing data from external platforms into nChat.
The Import & Migration Tools provide a comprehensive system for importing data from:
- Slack - Complete workspace exports with channels, users, messages, threads, and reactions
- Discord - Server exports with guilds, channels, messages, and embeds
- CSV - Generic CSV files with automatic field mapping
- JSON - Generic JSON files with flexible schema detection
- β Multi-platform support (Slack, Discord, CSV, JSON)
- β Complete import wizard with step-by-step guidance
- β Real-time progress tracking
- β Automatic field mapping for CSV/JSON
- β Error handling and recovery
- β Import validation and preview
- β Selective import (users, channels, messages, files)
- β Date range filtering
- β Channel filtering
- β Preserve threading and reactions
- β Duplicate detection
- β Cancel/retry support
- Import users with profile data
- Import channels (public/private)
- Import messages with full history
- Import file attachments
- Import message reactions
- Import thread conversations
- Date range filtering
- Channel filtering
- Preserve original IDs
- Overwrite existing data
src/
βββ lib/import/
β βββ types.ts # Type definitions
β βββ slack-importer.ts # Slack import service
β βββ discord-importer.ts # Discord import service
β βββ generic-importer.ts # CSV/JSON import service
β βββ index.ts # Main exports
βββ components/admin/
β βββ ImportData.tsx # Import wizard UI
βββ app/api/import/
βββ route.ts # Import API endpoint
1. Select Source (Slack/Discord/CSV/JSON)
β
2. Upload File
β
3. Configure Options
β
4. Validate & Parse
β
5. Import Data (with progress tracking)
β
6. Show Results & Statistics
Navigate to /admin/import to access the import wizard:
import ImportData from '@/components/admin/ImportData'
export default function ImportPage() {
return <ImportData />
}import { SlackImporter } from '@/lib/import'
const importer = new SlackImporter({
importUsers: true,
importChannels: true,
importMessages: true,
importFiles: true,
importReactions: true,
importThreads: true,
})
// Parse Slack export file
const slackData = await importer.parseSlackExport(file)
// Import with progress tracking
const result = await importer.import(slackData, (progress) => {
console.log(`${progress.currentStep}: ${progress.progress}%`)
console.log(`Processed: ${progress.itemsProcessed}/${progress.itemsTotal}`)
})
console.log('Import completed:', result.stats)import { DiscordImporter } from '@/lib/import'
const importer = new DiscordImporter({
importUsers: true,
importChannels: true,
importMessages: true,
})
const discordData = await importer.parseDiscordExport(file)
const result = await importer.import(discordData, (progress) => {
// Handle progress updates
})import { GenericImporter } from '@/lib/import'
const importer = new GenericImporter({
importUsers: true,
importChannels: false,
importMessages: false,
})
const csvData = await importer.parseCSV(file)
const result = await importer.import(csvData)import { GenericImporter } from '@/lib/import'
const mapping = {
users: {
id: 'user_id',
email: 'email_address',
username: 'login_name',
displayName: 'full_name',
},
}
const importer = new GenericImporter(options, mapping)
const jsonData = await importer.parseJSON(file)
const result = await importer.import(jsonData)- Go to your Slack workspace settings
- Navigate to Settings & administration β Workspace settings
- Click Import/Export Data
- Select Export tab
- Choose date range
- Click Start Export
- Download the ZIP file when ready
slack-export.zip
βββ channels.json # Channel definitions
βββ users.json # User profiles
βββ [channel-name]/ # Messages per channel
βββ 2024-01-01.json # Messages per day
βββ 2024-01-02.json
βββ ...
channels.json:
[
{
"id": "C123456",
"name": "general",
"created": 1234567890,
"creator": "U123456",
"is_archived": false,
"members": ["U123456", "U234567"],
"topic": {
"value": "General discussion",
"creator": "U123456",
"last_set": 1234567890
}
}
]users.json:
[
{
"id": "U123456",
"name": "john.doe",
"real_name": "John Doe",
"profile": {
"email": "john@example.com",
"display_name": "John",
"image_192": "https://..."
}
}
]Messages:
[
{
"type": "message",
"user": "U123456",
"text": "Hello world!",
"ts": "1234567890.123456",
"reactions": [
{
"name": "thumbsup",
"users": ["U234567"],
"count": 1
}
]
}
]- Parse Export: Extract and validate ZIP contents
- Import Users: Create user accounts (skip deleted users)
- Import Channels: Create channels (skip archived)
- Import Messages: Import messages with threading
- Import Files: Download and upload attachments
- Import Reactions: Add reactions to messages
Use DiscordChatExporter tool:
- Download from: https://github.com/Tyrrrz/DiscordChatExporter
- Run the tool and select your server
- Choose channels to export
- Select JSON format
- Export all selected channels
{
"guild": {
"id": "123456789",
"name": "My Server",
"iconUrl": "https://...",
"memberCount": 42
},
"channel": {
"id": "987654321",
"name": "general",
"topic": "General discussion"
},
"messages": [
{
"id": "111222333",
"type": "Default",
"timestamp": "2024-01-01T12:00:00+00:00",
"content": "Hello!",
"author": {
"id": "444555666",
"name": "JohnDoe",
"discriminator": "1234",
"avatarUrl": "https://..."
},
"reactions": [
{
"emoji": { "name": "π" },
"count": 3
}
]
}
]
}- Parse Export: Validate JSON structure
- Extract Users: Collect unique users from messages
- Import Users: Create accounts (skip bots)
- Import Channels: Create channels with categories
- Import Messages: Import with embeds and replies
- Import Attachments: Download and upload files
The importer automatically detects field names. Common patterns:
Users CSV:
id,email,username,display_name,role
1,john@example.com,john_doe,John Doe,member
2,jane@example.com,jane_smith,Jane Smith,adminChannels CSV:
id,name,description,is_private
1,general,General discussion,false
2,team,Team channel,trueMessages CSV:
id,channel_id,user_id,content,created_at
1,1,1,"Hello world!",2024-01-01T12:00:00Z
2,1,2,"Hi there!",2024-01-01T12:01:00ZStructured Format:
{
"users": [
{
"id": "1",
"email": "john@example.com",
"username": "john_doe",
"displayName": "John Doe"
}
],
"channels": [
{
"id": "1",
"name": "general",
"description": "General discussion"
}
],
"messages": [
{
"id": "1",
"channelId": "1",
"userId": "1",
"content": "Hello!",
"createdAt": "2024-01-01T12:00:00Z"
}
]
}Array Format:
[
{
"id": "1",
"email": "john@example.com",
"username": "john_doe"
}
]The importer automatically detects common field names:
User Fields:
-
id,user_id,userId -
email,email_address -
username,user_name,login -
display_name,displayName,full_name,name -
avatar,avatar_url,avatarUrl,photo,picture -
role,type,level
Channel Fields:
-
id,channel_id,channelId -
name,channel_name -
description,desc,topic,purpose -
private,is_private,isPrivate -
created_by,creator,owner
Message Fields:
-
id,message_id,messageId -
channel_id,channelId,room_id -
user_id,userId,author_id,sender_id -
content,text,message,body -
created_at,createdAt,timestamp,sent_at -
parent_id,parentId,thread_id,reply_to
const mapping = {
users: {
id: 'user_id',
email: 'user_email',
username: 'login_name',
displayName: 'full_name',
avatarUrl: 'profile_picture',
role: 'user_role',
},
channels: {
id: 'room_id',
name: 'room_name',
description: 'room_desc',
isPrivate: 'is_secure',
},
messages: {
id: 'msg_id',
channelId: 'room_id',
userId: 'sender_id',
content: 'message_text',
createdAt: 'sent_date',
},
}
const importer = new GenericImporter(options, mapping)interface ImportOptions {
// What to import
importUsers: boolean // Import user accounts
importChannels: boolean // Import channels
importMessages: boolean // Import message history
importFiles: boolean // Import file attachments
importReactions: boolean // Import message reactions
importThreads: boolean // Import threaded conversations
// Filters
dateRangeStart?: Date // Only import messages after this date
dateRangeEnd?: Date // Only import messages before this date
channelFilter?: string[] // Only import specific channels
userFilter?: string[] // Only import specific users
// Behavior
preserveIds: boolean // Try to preserve original IDs
overwriteExisting: boolean // Overwrite existing data vs skip
}Full Import:
{
importUsers: true,
importChannels: true,
importMessages: true,
importFiles: true,
importReactions: true,
importThreads: true,
preserveIds: false,
overwriteExisting: false,
}Users Only:
{
importUsers: true,
importChannels: false,
importMessages: false,
importFiles: false,
importReactions: false,
importThreads: false,
}Recent Messages Only:
{
importUsers: true,
importChannels: true,
importMessages: true,
importFiles: false,
importReactions: true,
importThreads: true,
dateRangeStart: new Date('2024-01-01'),
dateRangeEnd: new Date('2024-12-31'),
}Specific Channels:
{
importUsers: true,
importChannels: true,
importMessages: true,
importFiles: true,
importReactions: true,
importThreads: true,
channelFilter: ['general', 'announcements', 'team'],
}interface ImportProgress {
status: 'idle' | 'validating' | 'importing' | 'completed' | 'error' | 'cancelled'
currentStep: string
totalSteps: number
currentStepNumber: number
progress: number // 0-100
itemsProcessed: number
itemsTotal: number
errors: ImportError[]
warnings: ImportWarning[]
startedAt?: Date
completedAt?: Date
estimatedTimeRemaining?: number // seconds
}await importer.import(data, (progress) => {
console.log(`Step ${progress.currentStepNumber}/${progress.totalSteps}: ${progress.currentStep}`)
console.log(`Progress: ${progress.progress}%`)
console.log(`Items: ${progress.itemsProcessed}/${progress.itemsTotal}`)
if (progress.errors.length > 0) {
console.log(`Errors: ${progress.errors.length}`)
}
if (progress.warnings.length > 0) {
console.log(`Warnings: ${progress.warnings.length}`)
}
})interface ImportError {
type: 'user' | 'channel' | 'message' | 'file' | 'validation' | 'unknown'
message: string
details?: string
item?: unknown
timestamp: Date
recoverable: boolean
}interface ImportWarning {
type: 'skipped' | 'modified' | 'unsupported' | 'duplicate'
message: string
details?: string
item?: unknown
timestamp: Date
}const result = await importer.import(data)
if (!result.success) {
console.error('Import failed')
for (const error of result.progress.errors) {
console.error(`${error.type}: ${error.message}`)
if (error.recoverable) {
console.log('This error can be retried')
}
}
}
for (const warning of result.progress.warnings) {
console.warn(`${warning.type}: ${warning.message}`)
}interface ImportStats {
usersImported: number
usersSkipped: number
usersFailed: number
channelsImported: number
channelsSkipped: number
channelsFailed: number
messagesImported: number
messagesSkipped: number
messagesFailed: number
filesImported: number
filesSkipped: number
filesFailed: number
reactionsImported: number
threadsImported: number
totalDuration: number // milliseconds
}{
usersImported: 42,
usersSkipped: 3, // Bots or deleted users
usersFailed: 0,
channelsImported: 15,
channelsSkipped: 2, // Archived channels
channelsFailed: 0,
messagesImported: 15847,
messagesSkipped: 123, // Outside date range
messagesFailed: 5,
filesImported: 234,
filesSkipped: 12, // Too large or unsupported
filesFailed: 3,
reactionsImported: 1023,
threadsImported: 456,
totalDuration: 45382 // ~45 seconds
}Start Import:
POST /api/import
{
"source": "slack",
"options": {
"importUsers": true,
"importChannels": true,
"importMessages": true
},
"fileData": "base64EncodedFileContent",
"filename": "slack-export.zip"
}
Response:
{
"success": true,
"progress": { ... },
"stats": { ... }
}Get Import Status:
GET /api/import?id=import-123
Response:
{
"id": "import-123",
"status": "importing",
"progress": 65,
"stats": { ... }
}Cancel Import:
DELETE /api/import?id=import-123
Response:
{
"success": true,
"message": "Import cancelled"
}- Large Imports: For >10,000 messages, consider batching
- File Uploads: Compress large files before upload
- Progress Updates: Throttle progress callbacks to avoid UI lag
- Memory: Process messages in chunks for very large imports
- Validate First: Always preview data before importing
- Test Import: Test with small dataset first
- Backup: Backup existing data before large imports
- Deduplication: Enable duplicate detection when re-importing
- Field Mapping: Verify field mappings for CSV/JSON imports
- Retry Failed Items: Use recoverable error flag
- Incremental Import: Import in smaller batches
- Log Errors: Save error logs for debugging
- Rollback: Have a rollback plan for failed imports
"Failed to parse export file"
- Verify file format (ZIP for Slack, JSON for Discord)
- Check file is not corrupted
- Ensure export is complete (not partial)
"No users found in export"
- Check export includes user data
- Verify JSON structure is correct
- For Discord, users are extracted from messages
"Messages skipped"
- Check date range filters
- Verify channel filters
- Ensure parent channels are imported first
"File import failed"
- Check file size limits
- Verify file URLs are accessible
- Ensure sufficient storage space
"High memory usage"
- Process in smaller batches
- Reduce concurrent imports
- Clear cache between imports
- Background/async import with job queue
- Import scheduling
- Incremental sync (updates only)
- Custom transform functions
- Export to other formats
- Import templates/presets
- Bulk import management
- Import audit logs
- Advanced field transformations
- Multi-file imports
- Microsoft Teams import
- Mattermost import
- Rocket.Chat import
- Telegram import
- WhatsApp export import
- Email thread import
- RSS feed import
Part of nChat platform. See main LICENSE file.
For issues or questions:
- GitHub Issues: https://github.com/yourorg/nself-chat/issues
- Documentation: /docs
- Email: support@example.com
nself-chat v0.3.0 | GitHub | Issues | Discussions | Demo
Edit this page | MIT License | Β© 2026
(See π Security section below for 2FA, PIN Lock, and security audits.)
(Search lives in π Reference below.)
- π¬ Advanced Messaging
- π E2EE Setup
- π Search Setup
- π Call Management
- πΊ Live Streaming
- π₯οΈ Screen Sharing
- πΉ Video Calling
- ποΈ Voice Calling
- π± Mobile Optimization
- π§ͺ Testing
- π i18n
- π API Overview
- π Complete Reference
- π» API Examples
- π€ Bot API
- π Auth API
- π GraphQL Schema
- π Deployment Overview
- π³ Docker
- βΈοΈ Kubernetes
- β Helm Charts
- β Production Checklist
- π Production Validation
- π’ Multi-Tenant
- ποΈ Architecture
- π Diagrams
- ποΈ Database Schema
- π Project Structure
- π TypeScript Types
- π SPORT Reference
- π 2FA
- π¬ Messaging
- π Call Management
- π Call State Machine
- π E2EE
- πΊ Live Streaming
- π± Mobile Calls
- π PIN Lock
- π Polls
- π₯οΈ Screen Sharing
- π Search
- π Social Media
- ποΈ Voice Calling
- π Security Overview
- π‘οΈ Security Audit
- β‘ Performance
- π Best Practices
- π 2FA
- π PIN Lock
- π E2EE
- π‘οΈ E2EE Audit
v1.0.0 β’ 2026