Updated extensions information.
576
Extension-Development.md
Normal file
576
Extension-Development.md
Normal file
@ -0,0 +1,576 @@
|
||||
# Extension Development
|
||||
|
||||
TTYverse extensions are Perl scripts that integrate with TTYverse's event system to add custom functionality. This guide covers creating, testing, and deploying custom extensions.
|
||||
|
||||
## Extension Architecture
|
||||
|
||||
Extensions hook into TTYverse's multi-process architecture through defined callback functions:
|
||||
|
||||
- **`$handle`** - Called for each incoming post (main processing hook)
|
||||
- **`$addaction`** - Called for user commands (adds new slash commands)
|
||||
- **`$prepost`** - Called before sending posts
|
||||
- **`$postpost`** - Called after sending posts
|
||||
- **`$heartbeat`** - Called periodically for background tasks
|
||||
- **`$notifier`** - Called for notification events (sounds, desktop alerts, etc.)
|
||||
|
||||
## Available Variables
|
||||
|
||||
Extensions have access to these TTYverse variables:
|
||||
|
||||
### Core Variables
|
||||
- **`$whoami`** - Current user's username
|
||||
- **`$silent`** - Silent mode flag (suppress output when true)
|
||||
- **`$verbose`** - Verbose mode flag (show debug info when true)
|
||||
- **`$stdout`** - Output filehandle for user messages
|
||||
- **`$streamout`** - Output filehandle for timeline content
|
||||
|
||||
### File Paths
|
||||
- **`$data`** - XDG data directory (`~/.local/share/ttyverse`)
|
||||
- **`$config`** - XDG config directory (`~/.config/ttyverse`)
|
||||
- **`$store`** - Extension persistent storage hash
|
||||
|
||||
### Post Processing
|
||||
- **`&defaulthandle($ref)`** - Default post display function
|
||||
- **`&standardpost($ref, $text_only)`** - Format post for notifications
|
||||
- **`&findtarget($code)`** - Find post by menu code (a1, b3, etc.)
|
||||
- **`&descape($text)`** - Decode HTML entities and escape sequences safely
|
||||
- **`&common_split_post($text, $reply_to, $media)`** - Send posts via TTYverse
|
||||
|
||||
### Timeline State
|
||||
- **`$last_id`** - Current timeline position (0 during initial load)
|
||||
- **`$initial_load_in_progress`** - True during startup timeline fetch
|
||||
|
||||
### Environment Access
|
||||
- **`$ENV{'HOME'}`** - User's home directory
|
||||
- **`$ENV{'DISPLAY'}`** - X11 display (for GUI detection)
|
||||
- **`$ENV{'XDG_DATA_HOME'}`** - XDG data directory override
|
||||
- **`$ENV{'XDG_CONFIG_HOME'}`** - XDG config directory override
|
||||
|
||||
## Extension Types
|
||||
|
||||
### 1. Post Processing Extensions
|
||||
|
||||
Handle incoming posts and modify display:
|
||||
|
||||
```perl
|
||||
$handle = sub {
|
||||
my $post_ref = shift;
|
||||
my $class = shift; # Notification class (default, mention, dm, etc.)
|
||||
|
||||
# Your custom processing here
|
||||
# Access post data: $post_ref->{'content'}, $post_ref->{'account'}->{'username'}
|
||||
|
||||
# Always call default handler to display the post
|
||||
&defaulthandle($post_ref);
|
||||
return 1;
|
||||
};
|
||||
```
|
||||
|
||||
### 2. Command Extensions
|
||||
|
||||
Add new slash commands:
|
||||
|
||||
```perl
|
||||
$addaction = sub {
|
||||
my $command_line = $_; # Full command line input
|
||||
|
||||
if ($command_line =~ /^\/mycommand\s+(.*)$/) {
|
||||
my $args = $1;
|
||||
|
||||
# Process your command
|
||||
print $streamout "-- My command executed with: $args\n";
|
||||
return 1; # Command handled
|
||||
}
|
||||
|
||||
return 0; # Not our command, let TTYverse handle it
|
||||
};
|
||||
```
|
||||
|
||||
### 3. Notification Extensions
|
||||
|
||||
Handle sound, visual, or other notifications:
|
||||
|
||||
```perl
|
||||
sub notifier_mynotifier {
|
||||
my $class = shift; # Notification type (dm, mention, boost, etc.)
|
||||
my $text = shift; # Formatted notification text
|
||||
my $post_ref = shift; # Original post data
|
||||
|
||||
# Handle initialization (called with no $class)
|
||||
if (!defined($class)) {
|
||||
print $stdout "-- My notifier loaded\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
# Process notification based on class
|
||||
if ($class eq 'dm') {
|
||||
# Handle direct messages with higher priority
|
||||
} elsif ($class eq 'mention') {
|
||||
# Handle mentions
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
# Register the notifier (must be done globally)
|
||||
# TTYverse automatically finds functions named notifier_*
|
||||
```
|
||||
|
||||
### 4. Time-based Extensions
|
||||
|
||||
Extensions that perform actions based on time intervals:
|
||||
|
||||
```perl
|
||||
# Extension global variables for state tracking
|
||||
my $last_action_time = 0;
|
||||
my $first_run = 0;
|
||||
|
||||
$handle = sub {
|
||||
my $post_ref = shift;
|
||||
|
||||
# Initialize on first run
|
||||
if (!$first_run) {
|
||||
$first_run = 1;
|
||||
$last_action_time = time;
|
||||
print $stdout "-- Time-based extension loaded\n" if (!$silent);
|
||||
}
|
||||
|
||||
# Check if enough time has passed (5 minutes = 300 seconds)
|
||||
my $current_time = time;
|
||||
if ($current_time - $last_action_time >= 300) {
|
||||
$last_action_time = $current_time;
|
||||
|
||||
# Perform periodic action
|
||||
my ($sec,$min,$hour,$day,$mon,$year) = localtime($current_time);
|
||||
my $timestamp = sprintf("%02d:%02d", $hour, $min);
|
||||
print $streamout "-- $timestamp --\n" if (!$silent);
|
||||
}
|
||||
|
||||
# Always call default handler
|
||||
&defaulthandle($post_ref);
|
||||
return 1;
|
||||
};
|
||||
```
|
||||
|
||||
## Configuration and State Management
|
||||
|
||||
### RC File Configuration
|
||||
|
||||
Extensions can use configuration variables from the user's RC file:
|
||||
|
||||
```perl
|
||||
# In user's ~/.config/ttyverse/ttyverserc:
|
||||
# extpref_myext_setting=value
|
||||
# extpref_myext_enabled=1
|
||||
|
||||
# In your extension:
|
||||
my $setting = $extpref_myext_setting || "default_value";
|
||||
my $enabled = $extpref_myext_enabled || 0;
|
||||
```
|
||||
|
||||
### File-based Configuration Storage
|
||||
|
||||
For settings that change during runtime, use separate config files:
|
||||
|
||||
```perl
|
||||
# Read extension-specific config file
|
||||
my $config_file = "$ENV{'HOME'}/.config/ttyverse/myext_settings";
|
||||
my $setting_value;
|
||||
|
||||
if (-e $config_file) {
|
||||
open my $fh, '<', $config_file or die "Cannot read config: $!";
|
||||
$setting_value = <$fh>;
|
||||
close $fh;
|
||||
chomp($setting_value) if defined($setting_value);
|
||||
} else {
|
||||
$setting_value = "default";
|
||||
}
|
||||
|
||||
# Write extension-specific config file
|
||||
sub save_setting {
|
||||
my $value = shift;
|
||||
my $config_file = "$ENV{'HOME'}/.config/ttyverse/myext_settings";
|
||||
|
||||
open my $fh, '>', $config_file or die "Cannot write config: $!";
|
||||
print $fh $value;
|
||||
close $fh;
|
||||
}
|
||||
```
|
||||
|
||||
### XDG Directory Handling
|
||||
|
||||
Use XDG standards for cross-platform compatibility:
|
||||
|
||||
```perl
|
||||
# Get XDG-compliant data directory
|
||||
my $data_dir = $ENV{'XDG_DATA_HOME'} || "$ENV{'HOME'}/.local/share";
|
||||
my $ext_data_dir = "$data_dir/ttyverse";
|
||||
|
||||
# Get XDG-compliant config directory
|
||||
my $config_dir = $ENV{'XDG_CONFIG_HOME'} || "$ENV{'HOME'}/.config";
|
||||
my $ext_config_dir = "$config_dir/ttyverse";
|
||||
|
||||
# Create directories if needed
|
||||
mkdir $ext_data_dir unless -d $ext_data_dir;
|
||||
mkdir $ext_config_dir unless -d $ext_config_dir;
|
||||
```
|
||||
|
||||
### Persistent Storage with $store
|
||||
|
||||
Use the `$store` hash for data that persists during the TTYverse session:
|
||||
|
||||
```perl
|
||||
# Store data (survives between function calls)
|
||||
$store->{'my_counter'} = 0;
|
||||
$store->{'user_preferences'} = { volume => 50, enabled => 1 };
|
||||
|
||||
# Access stored data
|
||||
my $count = $store->{'my_counter'} || 0;
|
||||
$count++;
|
||||
$store->{'my_counter'} = $count;
|
||||
|
||||
# Complex data structures
|
||||
my $prefs = $store->{'user_preferences'} || {};
|
||||
$prefs->{'last_used'} = time;
|
||||
$store->{'user_preferences'} = $prefs;
|
||||
```
|
||||
|
||||
## Post Data Structure
|
||||
|
||||
Post references contain Mastodon API data:
|
||||
|
||||
```perl
|
||||
$post_ref = {
|
||||
'id' => '12345',
|
||||
'content' => 'Post text with <em>HTML</em>',
|
||||
'account' => {
|
||||
'username' => 'user',
|
||||
'acct' => 'user@domain.com',
|
||||
'display_name' => 'Display Name'
|
||||
},
|
||||
'mentions' => [
|
||||
{
|
||||
'username' => 'mentioned_user',
|
||||
'acct' => 'mentioned_user@domain.com'
|
||||
}
|
||||
],
|
||||
'created_at' => '2024-01-01T12:00:00Z',
|
||||
'visibility' => 'public'
|
||||
};
|
||||
```
|
||||
|
||||
## Notification Classes
|
||||
|
||||
TTYverse uses these notification classes:
|
||||
|
||||
- **`default`** - Regular timeline posts
|
||||
- **`mention`** - Posts that mention your username
|
||||
- **`dm`** - Direct messages (highest priority)
|
||||
- **`me`** - Your own posts
|
||||
- **`follow`** - New followers
|
||||
- **`boost`** - Your posts were boosted/shared
|
||||
- **`favourite`** - Your posts were favourited/liked
|
||||
- **`poll`** - Poll notifications
|
||||
- **`announcement`** - Server announcements
|
||||
|
||||
## Example: Complete Extension
|
||||
|
||||
Here's a comprehensive example extension that demonstrates multiple patterns:
|
||||
|
||||
```perl
|
||||
# Advanced Custom Extension
|
||||
# Adds /greet command and tracks greeting statistics
|
||||
# Demonstrates configuration, state management, and safe text processing
|
||||
|
||||
# Extension configuration with defaults
|
||||
my $enabled = $extpref_greet_enabled || 1;
|
||||
my $greeting_style = $extpref_greet_style || "friendly";
|
||||
|
||||
# Initialize extension state
|
||||
if (!$store->{'greet_loaded'}) {
|
||||
$store->{'greet_loaded'} = 1;
|
||||
$store->{'greet_count'} = 0;
|
||||
print $stdout "-- Greeting extension loaded (style: $greeting_style)\n" if (!$silent);
|
||||
}
|
||||
|
||||
# Command handler
|
||||
$addaction = sub {
|
||||
my $command = $_;
|
||||
|
||||
# Toggle extension on/off
|
||||
if ($command eq '/greet toggle') {
|
||||
my $config_file = "$ENV{'HOME'}/.config/ttyverse/greet_enabled";
|
||||
my $new_state = $enabled ? 0 : 1;
|
||||
|
||||
open my $fh, '>', $config_file or die "Cannot save config: $!";
|
||||
print $fh $new_state;
|
||||
close $fh;
|
||||
|
||||
$enabled = $new_state;
|
||||
my $status = $enabled ? "enabled" : "disabled";
|
||||
print $streamout "-- Greeting extension $status\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
# Show greeting statistics
|
||||
if ($command eq '/greet stats') {
|
||||
my $count = $store->{'greet_count'} || 0;
|
||||
print $streamout "-- Total greetings sent: $count\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
# Send greeting
|
||||
if ($command =~ /^\/greet\s+(\S+)\s*(.*)$/) {
|
||||
return 0 unless $enabled; # Respect user preference
|
||||
|
||||
my $username = $1;
|
||||
my $custom_message = $2;
|
||||
|
||||
# Clean and validate username
|
||||
$username = &descape($username);
|
||||
$username =~ s/^@//; # Remove @ if user included it
|
||||
|
||||
# Choose greeting based on style and custom message
|
||||
my $greeting;
|
||||
if ($custom_message) {
|
||||
$greeting = &descape($custom_message);
|
||||
} elsif ($greeting_style eq "formal") {
|
||||
$greeting = "Good day!";
|
||||
} elsif ($greeting_style eq "casual") {
|
||||
$greeting = "Hey there! 😊";
|
||||
} else { # friendly (default)
|
||||
$greeting = "Hello! 👋";
|
||||
}
|
||||
|
||||
# Send the greeting
|
||||
my $post_text = "\@$username $greeting";
|
||||
my $result = &common_split_post($post_text, undef, undef);
|
||||
|
||||
# Update statistics on success
|
||||
if ($result) {
|
||||
$store->{'greet_count'}++;
|
||||
print $stdout "-- Greeting sent to $username (total: $store->{'greet_count'})\n" if ($verbose);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
return 0; # Not our command
|
||||
};
|
||||
|
||||
# Post handler (optional - could add auto-greeting detection)
|
||||
$handle = sub {
|
||||
my $post_ref = shift;
|
||||
my $class = shift;
|
||||
|
||||
# Skip during initial load
|
||||
if ($last_id eq 0) {
|
||||
&defaulthandle($post_ref);
|
||||
return 1;
|
||||
}
|
||||
|
||||
# Could add logic here to detect greetings and respond
|
||||
# For now, just process normally
|
||||
&defaulthandle($post_ref);
|
||||
return 1;
|
||||
};
|
||||
|
||||
# Extension successfully loaded
|
||||
$store->{'loaded'} = 1;
|
||||
|
||||
# Required return value
|
||||
1;
|
||||
```
|
||||
|
||||
## Extension Development Workflow
|
||||
|
||||
### 1. Create Extension File
|
||||
```bash
|
||||
# Create extension in the extensions directory
|
||||
~/.local/share/ttyverse/extensions/myextension.pl
|
||||
```
|
||||
|
||||
### 2. Test Extension
|
||||
```bash
|
||||
# Test Perl syntax
|
||||
perl -c ~/.local/share/ttyverse/extensions/myextension.pl
|
||||
|
||||
# Load extension with TTYverse
|
||||
./ttyverse.pl -exts=myextension -verbose
|
||||
```
|
||||
|
||||
### 3. Debug Extension
|
||||
Use verbose mode to see debug output:
|
||||
```bash
|
||||
./ttyverse.pl -exts=myextension -verbose
|
||||
```
|
||||
|
||||
Add debug output in your extension:
|
||||
```perl
|
||||
print $stdout "-- DEBUG: My extension called\n" if ($verbose);
|
||||
```
|
||||
|
||||
## Advanced Extension Patterns
|
||||
|
||||
### Handling Initial Timeline Load
|
||||
|
||||
Prevent extension spam during startup by checking timeline state:
|
||||
|
||||
```perl
|
||||
$handle = sub {
|
||||
my $post_ref = shift;
|
||||
my $class = shift;
|
||||
|
||||
# Skip processing during initial timeline load
|
||||
if ($last_id eq 0) {
|
||||
&defaulthandle($post_ref);
|
||||
return 1;
|
||||
}
|
||||
|
||||
# Or use the more explicit flag
|
||||
if ($initial_load_in_progress) {
|
||||
&defaulthandle($post_ref);
|
||||
return 1;
|
||||
}
|
||||
|
||||
# Your extension logic here...
|
||||
&defaulthandle($post_ref);
|
||||
return 1;
|
||||
};
|
||||
```
|
||||
|
||||
### Safe Text Processing
|
||||
|
||||
Always use `&descape()` when processing post content:
|
||||
|
||||
```perl
|
||||
# Extract and clean post text
|
||||
my $author = &descape($post_ref->{'account'}->{'display_name'} ||
|
||||
$post_ref->{'account'}->{'username'});
|
||||
my $content = &descape($post_ref->{'content'});
|
||||
|
||||
# Additional cleaning for text-to-speech or notifications
|
||||
$content =~ s/<[^>]*>//g; # Remove HTML tags
|
||||
$content =~ s/&[a-zA-Z0-9]+;//g; # Remove remaining entities
|
||||
$content =~ s/https?:\/\/\S+/ link /g; # Replace URLs
|
||||
$content =~ s/#(\w+)/ hashtag $1 /g; # Make hashtags readable
|
||||
```
|
||||
|
||||
### Environment Detection
|
||||
|
||||
Check system capabilities before using features:
|
||||
|
||||
```perl
|
||||
# Check for GUI environment
|
||||
if (!$ENV{'DISPLAY'}) {
|
||||
print $stdout "-- Warning: No GUI display available\n" if (!$silent);
|
||||
return 1;
|
||||
}
|
||||
|
||||
# Check for required commands
|
||||
sub command_exists {
|
||||
my $cmd = shift;
|
||||
return system("which $cmd >/dev/null 2>&1") == 0;
|
||||
}
|
||||
|
||||
if (!command_exists('paplay')) {
|
||||
print $stdout "-- Warning: paplay not found, trying alternative\n" if (!$silent);
|
||||
# Try alternative commands...
|
||||
}
|
||||
```
|
||||
|
||||
### Notification Function Registration
|
||||
|
||||
Proper naming convention for notification handlers:
|
||||
|
||||
```perl
|
||||
# Function name must be: notifier_extensionname
|
||||
sub notifier_soundpack {
|
||||
my $class = shift;
|
||||
my $text = shift;
|
||||
my $post_ref = shift;
|
||||
|
||||
# TTYverse automatically discovers and calls functions matching this pattern
|
||||
# No explicit registration needed
|
||||
}
|
||||
|
||||
# Multiple notifiers can exist - TTYverse calls all of them
|
||||
sub notifier_myother {
|
||||
# Another notification handler
|
||||
}
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Error Handling
|
||||
```perl
|
||||
$handle = sub {
|
||||
my $post_ref = shift;
|
||||
|
||||
eval {
|
||||
# Your processing code here
|
||||
# ...
|
||||
};
|
||||
|
||||
if ($@) {
|
||||
print $stdout "-- Extension error: $@\n" if (!$silent);
|
||||
}
|
||||
|
||||
# Always call default handler
|
||||
&defaulthandle($post_ref);
|
||||
return 1;
|
||||
};
|
||||
```
|
||||
|
||||
### Persistent Storage
|
||||
```perl
|
||||
# Store data between sessions
|
||||
$store->{'my_data'} = "persistent value";
|
||||
|
||||
# Access stored data
|
||||
my $saved_value = $store->{'my_data'} || "default";
|
||||
```
|
||||
|
||||
### Respecting User Preferences
|
||||
```perl
|
||||
# Check if user wants your extension to be quiet
|
||||
return 1 if ($silent);
|
||||
|
||||
# Only show messages in verbose mode
|
||||
print $stdout "-- Extension info\n" if ($verbose && !$silent);
|
||||
```
|
||||
|
||||
## Extension Loading
|
||||
|
||||
Extensions must end with:
|
||||
```perl
|
||||
# Mark extension as successfully loaded
|
||||
$store->{'loaded'} = 1;
|
||||
|
||||
# Required Perl module return value
|
||||
1;
|
||||
```
|
||||
|
||||
## Testing Your Extension
|
||||
|
||||
1. **Syntax Check**: `perl -c yourextension.pl`
|
||||
2. **Load Test**: `./ttyverse.pl -exts=yourextension -verbose`
|
||||
3. **Function Test**: Try your commands/hooks with real data
|
||||
4. **Error Test**: Test with invalid inputs and network failures
|
||||
|
||||
## Distribution
|
||||
|
||||
To share your extension:
|
||||
|
||||
1. Add clear documentation header with license
|
||||
2. List any dependencies
|
||||
3. Provide configuration examples
|
||||
4. Test on different systems
|
||||
|
||||
See existing extensions in `~/.local/share/ttyverse/extensions/` for examples.
|
||||
|
||||
---
|
||||
|
||||
**See also:** [Extensions](Extensions) | [Configuration](Configuration) | [Commands Reference](Commands-Reference)
|
||||
|
||||
*Last updated: 2025-07-29*
|
181
Extensions.md
181
Extensions.md
@ -1,98 +1,177 @@
|
||||
# Extensions
|
||||
|
||||
TTYverse supports extensions that add functionality like sound notifications, text-to-speech, and desktop integration. Extensions are Perl scripts that integrate with TTYverse's multi-process architecture.
|
||||
TTYverse supports extensions that add functionality like sound notifications, text-to-speech, and desktop integration. Extensions enhance your fediverse experience with customizable features.
|
||||
|
||||
## Available Extensions
|
||||
|
||||
TTYverse includes several extensions that enhance the user experience:
|
||||
TTYverse includes several built-in extensions:
|
||||
|
||||
- **Sound Pack** - Audio notifications for different types of posts and events
|
||||
- **Text-to-Speech** - Speak posts and notifications aloud
|
||||
- **Desktop Notifications** - Visual notification bubbles
|
||||
- **Timestamp Enhancement** - Enhanced timestamp display options
|
||||
### Sound Pack Extension
|
||||
- **Purpose**: Audio notifications for different types of posts and events
|
||||
- **Sounds**: Default timeline, mentions, DMs, boosts, follows, polls, announcements
|
||||
- **Configuration**: Customizable sound packs and audio commands
|
||||
|
||||
Extensions are included with TTYverse but not enabled by default.
|
||||
### Text-to-Speech Extension
|
||||
- **Purpose**: Speak posts and notifications aloud for accessibility
|
||||
- **Engines**: espeak, festival, pico, cepstral, macOS say
|
||||
- **Features**: Configurable voice, speed, and language settings
|
||||
|
||||
## Extension Installation
|
||||
### Desktop Notifications Extension
|
||||
- **Purpose**: Visual notification bubbles on Linux/Unix desktops
|
||||
- **Requirements**: libnotify and Gtk2::Notify Perl module
|
||||
- **Integration**: Works with GNOME, KDE, and other desktop environments
|
||||
|
||||
### Extension Availability
|
||||
TTYverse includes core extensions in the installation:
|
||||
### Timestamp Extension
|
||||
- **Purpose**: Enhanced timestamp display with time gaps
|
||||
- **Features**: Shows timestamps when 5+ minutes pass between posts
|
||||
|
||||
## Installing Extensions
|
||||
|
||||
### Using the Extension Manager
|
||||
|
||||
TTYverse includes a management script for easy extension control:
|
||||
|
||||
```bash
|
||||
** attempting to load extensions
|
||||
** loading /home/user/.local/share/ttyverse/extensions/extensionname.pl
|
||||
** loaded extensions: extensionname
|
||||
# Show available extensions
|
||||
./extensions/manage-extensions.sh list
|
||||
|
||||
# Enable an extension
|
||||
./extensions/manage-extensions.sh enable soundpack
|
||||
|
||||
# Disable an extension
|
||||
./extensions/manage-extensions.sh disable soundpack
|
||||
|
||||
# Check extension status
|
||||
./extensions/manage-extensions.sh status soundpack
|
||||
```
|
||||
|
||||
### Extension Location
|
||||
Extensions are stored in:
|
||||
### Manual Installation
|
||||
|
||||
Extensions are stored in the XDG data directory:
|
||||
```
|
||||
~/.local/share/ttyverse/extensions/
|
||||
```
|
||||
|
||||
Load extensions when starting TTYverse:
|
||||
```bash
|
||||
./ttyverse.pl -exts=soundpack,tts,libnotifyperl
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
Extensions are configured through TTYverse settings:
|
||||
### Extension Settings
|
||||
Configure extensions in your TTYverse RC file (`~/.config/ttyverse/ttyverserc`):
|
||||
|
||||
```bash
|
||||
# View extension-related settings
|
||||
/get sound_enabled
|
||||
/get tts_enabled
|
||||
# Load extensions automatically
|
||||
exts=soundpack,tts
|
||||
|
||||
# Enable/disable extensions
|
||||
/set sound_enabled 1
|
||||
/set extension_name 0
|
||||
# Enable sound notifications
|
||||
notifytype=soundpack
|
||||
notifies=default,mention,dm,me,follow,boost,favourite
|
||||
|
||||
# Sound pack settings
|
||||
extpref_sound_command=paplay
|
||||
extpref_soundpack=default
|
||||
|
||||
# Text-to-speech settings
|
||||
extpref_tts_synthesizer=espeak
|
||||
extpref_tts_language=en-US
|
||||
extpref_tts_rate=175
|
||||
```
|
||||
|
||||
Configuration can also be edited directly in:
|
||||
```
|
||||
~/.config/ttyverse/ttyverse_rc
|
||||
### Runtime Configuration
|
||||
Some settings can be changed while TTYverse is running:
|
||||
|
||||
```bash
|
||||
# Toggle text-to-speech
|
||||
/tts
|
||||
|
||||
# Get TTS help
|
||||
/tts help
|
||||
```
|
||||
|
||||
## Extension Dependencies
|
||||
|
||||
Some extensions may require additional system packages. Check the documentation for your specific distribution to install:
|
||||
### Sound Pack Extension
|
||||
- **Audio system**: PulseAudio (paplay), ALSA (aplay), or similar
|
||||
- **Sound files**: OGG Vorbis format recommended
|
||||
- **Commands**: `paplay`, `play` (SoX), `ogg123`, or `mpv`
|
||||
|
||||
- **Audio support** - PulseAudio or similar audio system
|
||||
- **Text-to-speech** - TTS engines like espeak or festival
|
||||
- **Desktop notifications** - libnotify and related Perl modules
|
||||
### Text-to-Speech Extension
|
||||
- **Synthesizers**: `espeak` (recommended), `festival`, `pico2wave`
|
||||
- **Commercial**: Cepstral Swift (Linux), macOS `say` command
|
||||
- **Languages**: Depends on synthesizer (espeak supports many)
|
||||
|
||||
## Custom Extensions
|
||||
### Desktop Notifications Extension
|
||||
- **Perl module**: `Gtk2::Notify`
|
||||
- **System**: libnotify (`libnotify-dev` or similar package)
|
||||
- **Desktop**: GUI environment with `DISPLAY` variable set
|
||||
|
||||
### Creating Extensions
|
||||
Extensions are Perl scripts that follow TTYverse conventions. They can:
|
||||
Install dependencies on common distributions:
|
||||
|
||||
- Hook into post processing
|
||||
- React to different notification types
|
||||
- Add new commands
|
||||
- Integrate with system features
|
||||
```bash
|
||||
# Debian/Ubuntu
|
||||
sudo apt install libgtk2-notify-perl espeak pulseaudio-utils
|
||||
|
||||
### Extension Development
|
||||
See the existing extensions in `~/.local/share/ttyverse/extensions/` for examples of how to create custom functionality.
|
||||
# Fedora/RHEL
|
||||
sudo dnf install perl-Gtk2-Notify espeak pulseaudio-utils
|
||||
|
||||
# Arch Linux
|
||||
sudo pacman -S perl-gtk2-notify espeak pulseaudio
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Extension Issues
|
||||
### Extension Loading Issues
|
||||
```bash
|
||||
# Check if extensions are loading
|
||||
./ttyverse.pl -verbose
|
||||
# Check if extensions are loading properly
|
||||
./ttyverse.pl -exts=soundpack -verbose
|
||||
|
||||
# Test extension files manually
|
||||
perl ~/.local/share/ttyverse/extensions/extensionname.pl
|
||||
# Test extension syntax
|
||||
perl -c ~/.local/share/ttyverse/extensions/soundpack.pl
|
||||
|
||||
# Fix permissions if needed
|
||||
chmod +x ~/.local/share/ttyverse/extensions/*.pl
|
||||
# Check extension manager status
|
||||
./extensions/manage-extensions.sh list
|
||||
```
|
||||
|
||||
### Common Problems
|
||||
- **Permission denied** - Make extension files executable
|
||||
- **Missing dependencies** - Install required system packages
|
||||
- **Configuration errors** - Check settings in ttyverse_rc
|
||||
|
||||
For specific extension issues, check the [Troubleshooting](Troubleshooting) guide.
|
||||
**Extension not loading**
|
||||
- Check that the extension file exists in `~/.local/share/ttyverse/extensions/`
|
||||
- Verify the extension is enabled: `./extensions/manage-extensions.sh status extensionname`
|
||||
- Look for Perl syntax errors: `perl -c extensionname.pl`
|
||||
|
||||
**No sound notifications**
|
||||
- Test audio system: `paplay /usr/share/sounds/alsa/Front_Left.wav`
|
||||
- Check sound pack configuration in RC file
|
||||
- Verify sound files exist in `~/.local/share/ttyverse/sounds/default/`
|
||||
|
||||
**Text-to-speech not working**
|
||||
- Test synthesizer: `espeak "test message"`
|
||||
- Check TTS configuration: `/tts help`
|
||||
- Install required TTS engine packages
|
||||
|
||||
**Desktop notifications not appearing**
|
||||
- Verify GUI environment: `echo $DISPLAY`
|
||||
- Test notification system: `notify-send "Test"`
|
||||
- Install libnotify Perl module
|
||||
|
||||
### Getting Help
|
||||
|
||||
For specific extension issues, check the [Troubleshooting](Troubleshooting) guide or examine the extension source code for configuration examples.
|
||||
|
||||
## Creating Custom Extensions
|
||||
|
||||
Want to create your own extensions? See the [Extension Development](Extension-Development) guide for detailed information on:
|
||||
|
||||
- Extension architecture and hooks
|
||||
- Available functions and variables
|
||||
- Code examples and best practices
|
||||
- Testing and distribution
|
||||
|
||||
---
|
||||
|
||||
**See also:** [Configuration](Configuration) | [Troubleshooting](Troubleshooting) | [Installation](Installation)
|
||||
**See also:** [Extension Development](Extension-Development) | [Configuration](Configuration) | [Troubleshooting](Troubleshooting)
|
||||
|
||||
*Last updated: 2025-07-28*
|
||||
*Last updated: 2025-07-29*
|
Reference in New Issue
Block a user