{"id":51232405,"url":"https://github.com/yshalsager/grayjay-plugins","last_synced_at":"2026-06-28T17:30:37.763Z","repository":{"id":360569278,"uuid":"1250755557","full_name":"yshalsager/grayjay-plugins","owner":"yshalsager","description":null,"archived":false,"fork":false,"pushed_at":"2026-05-27T00:09:49.000Z","size":85,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-05-27T02:13:12.833Z","etag":null,"topics":["grayjay","grayjay-plugin","mp3quran","quran","tvquran"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yshalsager.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-27T00:07:24.000Z","updated_at":"2026-05-27T00:10:51.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/yshalsager/grayjay-plugins","commit_stats":null,"previous_names":["yshalsager/grayjay-plugins"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/yshalsager/grayjay-plugins","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yshalsager%2Fgrayjay-plugins","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yshalsager%2Fgrayjay-plugins/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yshalsager%2Fgrayjay-plugins/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yshalsager%2Fgrayjay-plugins/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yshalsager","download_url":"https://codeload.github.com/yshalsager/grayjay-plugins/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yshalsager%2Fgrayjay-plugins/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34898562,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-28T02:00:05.809Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["grayjay","grayjay-plugin","mp3quran","quran","tvquran"],"created_at":"2026-06-28T17:30:33.495Z","updated_at":"2026-06-28T17:30:37.754Z","avatar_url":"https://github.com/yshalsager.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Grayjay Plugins\n\n[![Install MP3Quran](https://img.shields.io/badge/Install-MP3Quran-2ea44f)](https://raw.githubusercontent.com/yshalsager/grayjay-plugins/master/plugins/mp3quran/Mp3QuranConfig.json)\n[![Install tvQuran](https://img.shields.io/badge/Install-tvQuran-2ea44f)](https://raw.githubusercontent.com/yshalsager/grayjay-plugins/master/plugins/tvquran/TvQuranConfig.json)\n[![Install Archive.org](https://img.shields.io/badge/Install-Archive.org-2ea44f)](https://raw.githubusercontent.com/yshalsager/grayjay-plugins/master/plugins/archiveorg/ArchiveOrgConfig.json)\n[![Install Mixlr](https://img.shields.io/badge/Install-Mixlr-2ea44f)](https://raw.githubusercontent.com/yshalsager/grayjay-plugins/master/plugins/mixlr/MixlrConfig.json)\n[![Install AlBadr](https://img.shields.io/badge/Install-AlBadr-2ea44f)](https://raw.githubusercontent.com/yshalsager/grayjay-plugins/master/plugins/albadr/AlBadrConfig.json)\n\n[Grayjay](https://grayjay.app/) plugins in one repository. Current sources:\n\n- `plugins/mp3quran`: [MP3Quran.net](https://mp3quran.net) reciters, moshaf playlists, surah tracks with ayah chapters/subtitles, tafsir audio/playlists, reminder video playlists, recent reads, live Quran radio streams, and live TV using the public v3 API.\n- `plugins/tvquran`: [tvQuran.com](https://tvquran.com) Arabic/English/German recitation selections, category/collection playlists, reciter channels, direct collection links, richer category/video channel metadata, reciter/surah/category filters, direct MP3 links, recommendations, and nested YouTube video/live/prayer-recitation links from the public site pages.\n- `plugins/archiveorg`: [Internet Archive](https://archive.org) search-only audio/video plugin with Archive.org item playlists, direct playable file details, and direct `/details` or `/download` URL handling.\n- `plugins/mixlr`: [Mixlr](https://mixlr.com) public live audio channels/events, popular/category/search live feeds, channel search, direct channel/event URL handling, live MP3 playback, channel peeks, and recommendations.\n- `plugins/albadr`: [AlBadr](https://www.al-badr.net) Sheikh Abdul Razzaq al-Badr lessons with latest/selected home feeds, category channels, series playlists, direct MP3 lesson playback, search, recommendations, and nested Mixlr live content.\n\nPlugin icons come from the original source sites:\n\n- MP3Quran: `https://www.mp3quran.net/img/logo2.png`\n- tvQuran: `https://tvquran.com/bundles/tvquran/img/favicon/apple-touch-icon-144x144-precomposed.png`\n- Archive.org: `https://archive.org/images/glogo.png`\n- Mixlr: `https://mixlr.com/favicon.ico`\n- AlBadr: `https://www.al-badr.net/assets/images/logo-albadr.png` vendored as `plugins/albadr/AlBadrIcon.png`\n\nInstall URLs need to point at hosted raw config files after publishing this repo. The config files currently target this GitHub raw layout:\n\n- `https://raw.githubusercontent.com/yshalsager/grayjay-plugins/master/plugins/mp3quran/Mp3QuranConfig.json`\n- `https://raw.githubusercontent.com/yshalsager/grayjay-plugins/master/plugins/tvquran/TvQuranConfig.json`\n- `https://raw.githubusercontent.com/yshalsager/grayjay-plugins/master/plugins/archiveorg/ArchiveOrgConfig.json`\n- `https://raw.githubusercontent.com/yshalsager/grayjay-plugins/master/plugins/mixlr/MixlrConfig.json`\n- `https://raw.githubusercontent.com/yshalsager/grayjay-plugins/master/plugins/albadr/AlBadrConfig.json`\n\n## Playlist Support\n\n- MP3Quran reciter channels expose one playlist per moshaf. Global playlist search also exposes tafsir-source playlists and video-type playlists.\n- tvQuran category channels expose audio selection playlists, and reciter channels expose moshaf/collection playlists parsed from the reciter profile. tvQuran video categories stay as channel/content results because Grayjay playlist details require video items, while these entries are nested YouTube links.\n- Direct tvQuran collection URLs are recognized as both channel URLs and playlist URLs, so shared collection links can open into either navigation surface depending on what Grayjay asks for.\n- Archive.org exposes items as playlists, with each playable audio/video file represented as a playlist entry. It does not provide a home feed; use search to discover items.\n- Mixlr is live-only in v1; it intentionally does not expose playlists until recordings or collections are implemented as concrete playable lists.\n- AlBadr exposes each `/sub/{id}` lesson series as a playlist, category channels expose their series through channel playlists, and the site live page is represented as nested Mixlr content.\n\n## MP3Quran Ayah Text\n\nMP3Quran surah tracks use MP3Quran's ayah timing API for timed chapters. Quran text is fetched lazily per surah from `fawazahmed0/quran-api` using `ara-quransimple`.\n\nAndroid clients that support plugin subtitle sources can use the generated WebVTT subtitle source. Grayjay Desktop currently plays direct MP3 audio through a path that does not attach external subtitles, so the plugin also includes the ayah text in chapter labels as the Desktop fallback.\n\n## Development\n\n### Android\n\nUse Grayjay's Android DevServer while serving this repository from your computer on the same network.\n\n1. Enable developer mode in Grayjay:\n   - Open Grayjay on Android.\n   - Go to `More` -\u003e `Settings`.\n   - Scroll to the bottom and tap `Version Code` repeatedly.\n\n2. Start Grayjay DevServer:\n   - In Grayjay settings, open `Developer Settings`.\n   - Tap `Start Server`.\n   - Note the phone IP address from Android Wi-Fi/network settings.\n\n3. Serve this repo from your computer:\n\n   ```sh\n   cd \u003crepo\u003e\n   pnpm run dev\n   ```\n\n   The dev server rebuilds plugin scripts when `src/**` or `plugins/registry.json` changes, then serves the generated files from `plugins/**`.\n\n4. Open the DevServer in your computer browser:\n\n   ```text\n   http://PHONE_IP:11337/dev\n   ```\n\n5. Load a plugin using your computer LAN IP, not `localhost`:\n\n   ```text\n   http://COMPUTER_IP:3000/plugins/mp3quran/Mp3QuranConfig.json\n   http://COMPUTER_IP:3000/plugins/tvquran/TvQuranConfig.json\n   http://COMPUTER_IP:3000/plugins/archiveorg/ArchiveOrgConfig.json\n   http://COMPUTER_IP:3000/plugins/mixlr/MixlrConfig.json\n   http://COMPUTER_IP:3000/plugins/albadr/AlBadrConfig.json\n   ```\n\n6. In the DevServer UI:\n   - Click `Load Plugin` to test individual methods.\n   - Use the `Integration` tab and click `Inject Plugin` to test inside the Android app.\n   - Click refresh or inject again after local edits.\n\nThe phone must be able to reach your computer over the LAN, and your firewall must allow inbound connections to port `3000`.\n\n### Desktop\n\nUse Grayjay Desktop's Developer Portal while serving this repository from your computer.\n\n1. Enable developer mode by creating a `DEV` file in Grayjay Desktop's data directory.\n\n   On macOS:\n\n   ```sh\n   mise run grayjay-desktop-dev-mode\n   ```\n\n   Restart Grayjay Desktop after creating the file.\n\n2. Serve this repo from your computer:\n\n   ```sh\n   cd \u003crepo\u003e\n   pnpm run dev\n   ```\n\n   The dev server rebuilds plugin scripts when `src/**` or `plugins/registry.json` changes, then serves the generated files from `plugins/**`.\n\n3. Find Grayjay Desktop's local server port:\n\n   ```sh\n   mise run grayjay-desktop-port\n   ```\n\n4. Open the Developer Portal in your browser:\n\n   ```sh\n   mise run grayjay-desktop-dev\n   ```\n\n5. Load a plugin using the local config URL:\n\n   ```text\n   http://127.0.0.1:3000/plugins/mp3quran/Mp3QuranConfig.json\n   http://127.0.0.1:3000/plugins/tvquran/TvQuranConfig.json\n   http://127.0.0.1:3000/plugins/archiveorg/ArchiveOrgConfig.json\n   http://127.0.0.1:3000/plugins/mixlr/MixlrConfig.json\n   http://127.0.0.1:3000/plugins/albadr/AlBadrConfig.json\n   ```\n\n6. In the Developer Portal:\n   - Click `Load Plugin` to test individual methods.\n   - Use the `Integration` tab and click `Inject Plugin` to test inside Grayjay Desktop.\n   - Click refresh or inject again after local edits.\n\nSigning is not needed during local development. Grayjay Desktop normally listens on loopback with a random port written to the `port` file. Desktop also has a `--server` mode that binds on port `11338`.\n\n#### Desktop Debugging Notes\n\nDesktop has two useful log surfaces, and they show different failures:\n\n```sh\ntail -n 200 \"$HOME/Library/Application Support/Grayjay/log.txt\"\ncurl -sS \"http://127.0.0.1:$(cat \"$HOME/Library/Application Support/Grayjay/port\")/Developer/GetDevLogs?index=0\"\n```\n\n`log.txt` is the backend log. The Developer log endpoint is available without the private UI token and shows plugin method calls such as `search`, `isContentDetailsUrl`, and `getContentDetails`. A successful `getContentDetails` only proves the plugin returned a details object; it does not prove Desktop selected a source or the CEF media element started playback.\n\nThe normal player endpoints, including `/details/SourceAuto` and `/details/SourceProxy`, require Grayjay Desktop's private `_token` header. Direct `curl` calls without that token fail with `No valid token`, which is expected and not a plugin failure.\n\nFor endpoint debugging without copying the UI token, start Desktop server mode:\n\n```sh\nmise run grayjay-desktop-server-unsafe\n```\n\nThat launches Grayjay Desktop with `--server --ignore-security` and exposes debug endpoints at:\n\n```text\nhttp://127.0.0.1:11338\n```\n\nThen inject the local dev plugin into that server-mode process:\n\n```sh\nmise run grayjay-load-dev-plugin -- --plugin archiveorg\n```\n\nThis posts the local config from `http://127.0.0.1:3000/plugins/archiveorg/ArchiveOrgConfig.json`, rewrites the script URL to the local dev server, and enables the injected plugin as `DEV`.\n\nDesktop API quick check:\n\n```sh\nbase=http://127.0.0.1:11338\nidentifier='ARCHIVE_IDENTIFIER'\nurl=\"https%3A%2F%2Farchive.org%2Fdetails%2F$identifier\"\n\ncurl -sS \"$base/details/VideoLoad?url=$url\"\ncurl -sS \"$base/details/SourceAuto\"\ncurl -sS \"$base/Developer/GetDevLogs?index=0\"\n```\n\n`VideoLoad` asks the enabled plugin for content details and stores that item as Desktop's current video. `SourceAuto` asks Desktop to choose the source it would hand to the player. For audio-only Archive items it should return `audioIndex: 0` and a direct `audio/*` URL; for video items it should return `videoIndex: 0` and a direct `video/*` URL.\n\nTo inspect a specific source index explicitly:\n\n```sh\ncurl -sS \"$base/details/SourceProxy?videoIndex=-1\u0026audioIndex=0\u0026subtitleIndex=-1\u0026videoIsLocal=false\u0026audioIsLocal=false\u0026subtitleIsLocal=false\u0026tag=debug\"\n```\n\nWhen playback fails after `getContentDetails` succeeds:\n\n- Open Grayjay Desktop devtools and check the browser console for `source auto`, `Direct url`, `Player error`, `HLS player error`, or `DashJS` messages. These are emitted by the Desktop web player and do not appear in the Developer log.\n- Check whether the loaded config is the local dev URL in `lastDevUrl`:\n\n  ```sh\n  cat \"$HOME/Library/Application Support/Grayjay/lastDevUrl\"\n  ```\n\n- Rebuild before reinjecting; generated scripts are what Desktop loads:\n\n  ```sh\n  pnpm run build -- --plugin archiveorg\n  ```\n\n- Prefer direct Archive file hosts from metadata (`https://ia*.archive.org/.../items/...`) over `https://archive.org/download/...` redirect URLs for media sources. Desktop's player path is easier to debug when the final media URL is already resolved.\n- If inspecting Desktop behavior, fetch the missing engine submodule/source separately. The Desktop repo references `Grayjay.Engine`; that source contains the JS-to-model conversion for `VideoSourceDescriptor`, `UnMuxVideoSourceDescriptor`, `VideoUrlSource`, and `AudioUrlSource`.\n\n### Build Flow\n\nPlugin source lives in `src/plugins/\u003cplugin\u003e/index.js`. Do not edit generated `plugins/\u003cplugin\u003e/*Script.js` files directly unless you are debugging generated output.\n\nAfter source edits, rebuild the generated Grayjay scripts:\n\n```sh\npnpm run build:all\n```\n\nFor one plugin:\n\n```sh\npnpm run build -- --plugin mp3quran\n```\n\nCommit both the source changes under `src/**` and the generated `plugins/**/*Script.js` output. Signing should happen only after this build step; validation and signing both fail when a source file is newer than its generated script.\n\n### Scaffold Plugin\n\nCreate a new registry entry, config, source entry, generated script, and live test placeholder:\n\n```sh\npnpm run scaffold -- --value midad --label \"Midad\" --stem Midad --platform-url https://midad.com\n```\n\nRun `pnpm run scaffold` without flags for an interactive prompt.\n\nThe same task is available through mise:\n\n```sh\nmise run scaffold -- --value midad --label \"Midad\" --stem Midad --platform-url https://midad.com\n```\n\nUse `--dry-run` to preview without writing files. Pass `--icon-url` when the default `/favicon.ico` is not suitable.\n\n### Validation\n\n```sh\npnpm run validate\n```\n\nValidation checks the source entry files, generated scripts, plugin configs, local icon paths, and source/script freshness.\n\n### Style and Lint\n\n```sh\npnpm run format\npnpm run format:check\npnpm run lint\npnpm run check\n```\n\n`check` runs formatting, linting, `pnpm run build:all`, validation, and unit tests.\n\n### Git Hooks\n\nInstall Lefthook once after cloning:\n\n```sh\nlefthook install\n```\n\nThe pre-commit hook runs `pnpm run format`, `pnpm run lint:fix`, and `pnpm run validate`, then stages fixed files.\n\n### Bump and Signing\n\nBump versions and sign scripts only after final source edits and `pnpm run build:all`, because any generated script change invalidates the signature.\n\nInstall local tooling once:\n\n```sh\npnpm install\n```\n\n```sh\npnpm run bump\npnpm run sign\npnpm run sign-bump\n```\n\nThe prompted tasks let you select plugins, enter changelog entries when bumping, and choose a signing key when signing. The signing key defaults to `$GRAYJAY_SIGN_KEY`. `bump` writes the next `version` and `changelog`, `sign` writes `scriptSignature` and `scriptPublicKey`, and `sign-bump` does both in one flow. Signing refuses stale generated scripts, so run the build first.\n\nThe same tasks can run non-interactively:\n\n```sh\npnpm run bump -- --plugin mp3quran --message \"Release notes\" --yes --no-input\npnpm run sign -- --plugin all --key ~/.ssh/ysh --yes --no-input\npnpm run sign-bump -- --plugin all --message \"Release notes\" --key ~/.ssh/ysh --yes --no-input\n```\n\nUse `--dry-run` to preview without writing files. `--plugin` accepts `mp3quran`, `tvquran`, `archiveorg`, `mixlr`, `albadr`, or `all`, and can be repeated or comma-separated.\n\n## Sources\n\n- [MP3Quran website](https://mp3quran.net)\n- [MP3Quran API docs](https://mp3quran.net/ar/api)\n- [MP3Quran ayah timing reads](https://www.mp3quran.net/api/v3/ayat_timing/reads)\n- [tvQuran website](https://tvquran.com)\n- [Quran text repository](https://github.com/fawazahmed0/quran-api)\n- [Quran text CDN pattern](https://cdn.jsdelivr.net/gh/fawazahmed0/quran-api@1/editions/ara-quransimple/{surah}.min.json)\n- [Internet Archive metadata API](https://archive.org/developers/md-read.html)\n- [Internet Archive files, formats, and derivatives guide](https://help.archive.org/help/files-formats-and-derivatives-a-basic-guide/)\n- [Internet Archive search API](https://doc-tools.readthedocs.io/en/ia-test-gsod/item-search-apis.html)\n- [AlBadr website](https://www.al-badr.net)\n- [Grayjay plugin development docs](https://gitlab.futo.org/videostreaming/grayjay/-/blob/master/plugin-development.md)\n- [Grayjay sample plugin](https://gitlab.futo.org/videostreaming/plugins/sample)\n- [Grayjay RadioBrowser plugin](https://gitlab.futo.org/videostreaming/plugins/radiobrowser)\n\n## License\n\nThis repository is licensed under the GNU Affero General Public License v3.0 or later. See `LICENSE`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyshalsager%2Fgrayjay-plugins","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyshalsager%2Fgrayjay-plugins","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyshalsager%2Fgrayjay-plugins/lists"}