spotube/LYRICS_PLUGIN_TEMPLATE.md
2025-12-07 23:36:39 +08:00

290 lines
6.4 KiB
Markdown

# Lyrics Plugin Template Repository
This document provides a complete template for creating a lyrics plugin repository.
## Repository Structure
```
spotube-plugin-lrclib-lyrics/
├── .github/
│ └── workflows/
│ └── release.yml
├── src/
│ └── main.ht
├── plugin.json
├── logo.png
├── README.md
├── LICENSE
└── .gitignore
```
## File Contents
### plugin.json
```json
{
"name": "LrcLib Lyrics",
"author": "YourName",
"description": "Free and open-source lyrics provider using LrcLib API",
"version": "1.0.0",
"pluginApiVersion": "2.0.0",
"entryPoint": "LrcLibLyricsPlugin",
"repository": "https://github.com/yourusername/spotube-plugin-lrclib-lyrics",
"apis": [],
"abilities": ["lyrics"]
}
```
### src/main.ht
```hetu
import 'package:spotube_plugin/spotube_plugin.dart'
class LrcLibLyricsPlugin {
LrcLibLyricsPlugin() {
print('LrcLib Lyrics Plugin v1.0.0 initialized')
}
var lyrics = LyricsEndpoint()
}
class LyricsEndpoint {
external fun search(Map params) async {
final trackName = params['trackName']
final artistName = params['artistName']
final albumName = params['albumName']
final duration = params['duration']
var url = 'https://lrclib.net/api/search?track_name=${Uri.encodeComponent(trackName)}&artist_name=${Uri.encodeComponent(artistName)}'
if (albumName != null && albumName.isNotEmpty) {
url += '&album_name=${Uri.encodeComponent(albumName)}'
}
try {
final response = await http.get(url)
if (response.statusCode != 200) {
print('LrcLib API error: ${response.statusCode}')
return []
}
final data = json.decode(response.body)
if (data is! List) {
return []
}
final results = []
for (var item in data) {
final syncedLyrics = item['syncedLyrics']
final plainLyrics = item['plainLyrics']
if (syncedLyrics == null && plainLyrics == null) {
continue
}
results.add({
'uri': 'lrclib:${item['id']}',
'name': '${item['trackName']} - ${item['artistName']}',
'lyrics': parseLrc(syncedLyrics ?? plainLyrics ?? ''),
'rating': 5,
'provider': 'lrclib'
})
}
return results
} catch (e) {
print('LrcLib search error: $e')
return []
}
}
external fun getById(String id) async {
final url = 'https://lrclib.net/api/get/$id'
try {
final response = await http.get(url)
if (response.statusCode != 200) {
return null
}
final data = json.decode(response.body)
final syncedLyrics = data['syncedLyrics']
final plainLyrics = data['plainLyrics']
if (syncedLyrics == null && plainLyrics == null) {
return null
}
return {
'uri': 'lrclib:${data['id']}',
'name': '${data['trackName']} - ${data['artistName']}',
'lyrics': parseLrc(syncedLyrics ?? plainLyrics ?? ''),
'rating': 5,
'provider': 'lrclib'
}
} catch (e) {
print('LrcLib getById error: $e')
return null
}
}
external fun isAvailable() async {
try {
final response = await http.get('https://lrclib.net/')
return response.statusCode == 200
} catch (e) {
return false
}
}
fun parseLrc(String lrcContent) {
if (lrcContent.isEmpty) {
return []
}
final lines = lrcContent.split('\n')
final lyrics = []
for (var line in lines) {
final timeMatch = RegExp(r'\[(\d+):(\d+)\.(\d+)\]').firstMatch(line)
if (timeMatch != null) {
final minutes = int.parse(timeMatch.group(1))
final seconds = int.parse(timeMatch.group(2))
final centiseconds = int.parse(timeMatch.group(3))
final text = line.substring(timeMatch.end).trim()
if (text.isNotEmpty) {
final timeMs = (minutes * 60 + seconds) * 1000 + centiseconds * 10
lyrics.add({
'time': timeMs,
'text': text
})
}
}
}
return lyrics
}
}
```
### README.md
```markdown
# LrcLib Lyrics Plugin for Spotube
Free and open-source lyrics provider using the LrcLib API.
## Features
- Time-synced lyrics
- Free and open-source
- No API key required
- Large lyrics database
## Installation
1. Open Spotube
2. Go to Settings > Plugins
3. Click "Add Plugin"
4. Paste: `https://github.com/yourusername/spotube-plugin-lrclib-lyrics`
5. Click Install
## Building
### Prerequisites
- Dart SDK
- Hetu Script Dev Tools
### Compile
```bash
dart pub global activate hetu_script_dev_tools
hetu compile src/main.ht -o plugin.out
```
### Package
```bash
zip spotube-plugin-lrclib-lyrics.smplug plugin.json plugin.out logo.png
```
## API
This plugin uses the [LrcLib API](https://lrclib.net/docs).
## License
MIT License
```
### .github/workflows/release.yml
```yaml
name: Release Plugin
on:
push:
tags:
- 'v*'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: dart-lang/setup-dart@v1
- name: Install Hetu
run: dart pub global activate hetu_script_dev_tools
- name: Compile Plugin
run: hetu compile src/main.ht -o plugin.out
- name: Package Plugin
run: zip spotube-plugin-lrclib-lyrics.smplug plugin.json plugin.out logo.png
- name: Create Release
uses: softprops/action-gh-release@v1
with:
files: spotube-plugin-lrclib-lyrics.smplug
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```
### .gitignore
```
plugin.out
*.smplug
.DS_Store
```
## Publishing
1. Create repository on GitHub
2. Push code
3. Create a tag: `git tag v1.0.0`
4. Push tag: `git push origin v1.0.0`
5. GitHub Actions will automatically build and release
## Testing Locally
1. Compile: `hetu compile src/main.ht -o plugin.out`
2. Package: `zip plugin.smplug plugin.json plugin.out logo.png`
3. In Spotube, add plugin via file path
## Example Plugins
- [spotube-plugin-youtube-audio](https://github.com/KRTirtho/spotube/tree/master/assets/plugins/spotube-plugin-youtube-audio)
- [spotube-plugin-musicbrainz-listenbrainz](https://github.com/KRTirtho/spotube/tree/master/assets/plugins/spotube-plugin-musicbrainz-listenbrainz)