# hafrey1/LunaTV-config: a Base58 subscription builder for MoonTV/LunaTV

> This repository is a source list plus a Cloudflare Worker that rewrites API prefixes and encodes the result as Base58. It is built for people running MoonTV or LunaTV who want a subscription URL, not for people who want an app.

**hafrey1/LunaTV-config** — MoonTV/LunaTV源配置，每日自动检测API状态，可在CF部署CORSAPI中转被墙API，本人提供的CORSAPI仅为测试使用，请勿滥用！

- Repository: https://github.com/hafrey1/LunaTV-config
- Website: https://pz.v88.qzz.io
- Stars: 4,283 · Forks: 1,631
- Language: JavaScript
- License: not declared
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/hafrey1-lunatv-config

## What LunaTV-config actually ships

The repository is not a player. It is a set of source definitions for MoonTV and LunaTV, three of them, plus the tooling to serve them. The README names them jin18 (31 resources, no adult content), jingjian (61 resources, adult content included) and full (88 resources, the default). Each exists as a .json file and a .txt file at the repository root, and the .txt form is the Base58 encoded one that a client consumes as a subscription. The README points at raw.githubusercontent.com URLs for direct use and at the author's own host pz.v88.qzz.io for the Worker-mediated form.

The audience is narrow and worth stating plainly. If you have never installed MoonTV or LunaTV, nothing here helps you; the README assumes you already have a client that accepts a subscription link. If you do run one of those, the value is that someone else has already assembled and deduplicated a source list, and that check_api.js and report.md exist in the tree, which suggests a status check runs against those sources on a schedule. The README's own description says the API status is checked daily.

## How the Worker rewrites api fields and returns Base58

The mechanism is a single Cloudflare Worker, _worker.js, that does two jobs. The first is a generic forwarder: a request with ?url= is passed through to the target API, which is what makes it a CORS proxy. The second is a transform on the stored configuration. The Worker holds the source lists under a JSON_SOURCES object, keyed by the three source names, and serves them through four output modes controlled by the format parameter: format=0 or raw returns the JSON untouched, format=1 or proxy injects a proxy prefix into each api field, format=2 or base58 returns the raw JSON Base58 encoded, and format=3 or proxy-base58 does both.

The prefix logic is the part worth understanding before you deploy. If an api field already carries an old ?url= prefix, the Worker strips it and applies the new one rather than stacking them. You can override the prefix entirely with ?prefix=https://my-proxy.com/?url=, which is how you point the list at your own forwarder instead of the author's. Responses are cached for 7200 seconds, and requests time out after 9 seconds. There is a parameter the README documents as errors&limit=10 for reading the error log, which implies failed upstream checks are recorded rather than silently dropped. The README does not say where that log is stored; the optional CONFIG_KV binding is the only persistence the deployment steps mention, and the README never states that the error log uses it.

## Deploying the Worker and pulling a first subscription

The README gives two deployment paths. The Workers path is the shorter one: create a Worker from the Hello World template in the Cloudflare dashboard, paste the contents of _worker.js into the online editor, and save and deploy. The Pages path is the same file dropped into an empty folder and uploaded as static assets. Neither path requires the KV namespace; the README marks it optional and, if used, the binding variable name is CONFIG_KV.

Once the Worker is live, the first useful request is a raw fetch, to confirm the source list resolves before you wrap it in Base58. The README's own example for a raw configuration is this form:

```bash
https://api.example.workers.dev/?format=0&source=jingjian
```

Substitute your own Worker domain. You should get JSON back, not an error string. If the upstream fetch times out you will get the error response instead, and the 9 second default is the reason.

Next, check that the prefix injection does what you expect, using your own proxy rather than the author's. The README documents the prefix override as:

```bash
https://api.example.workers.dev/?format=1&source=full&prefix=https://my-proxy.com/?url=
```

Inspect one api field in the output. It should carry your prefix once, with any previous ?url= prefix removed.

The form you actually paste into a client is format=3, the proxied Base58 subscription:

```bash
https://api.example.workers.dev/?format=3&source=jingjian
```

The README lists this combination as the recommended one for subscriptions. If your client rejects it, the failure is on the client side: not every client accepts Base58 subscription links, and the README does not name which ones do.

## The resource counts and the timeout are the real constraints

Two numbers define the practical limits. The first is 9 seconds, the default request timeout. A source that is slow rather than dead will fail the same way a dead one does, and the README's answer to that is the error log, not a retry policy. The second is the Cloudflare Workers free tier, which the README states as 100,000 requests per day. A subscription URL that a client refreshes on a timer multiplies quickly if several devices point at the same Worker, and the README's advice for heavy use is to upgrade to a paid plan rather than to cache harder. The 7200 second cache helps only for repeat requests of the same source and format combination.

There is a licensing problem the repository does not resolve. No licence file is listed in the top-level entries, and the README does not state terms for the source lists or for _worker.js. That is not a detail you can settle by reading the code. If you intend to redistribute the lists or run the Worker as a public service, the terms are simply not stated anywhere, and the README's request not to abuse the author's CORSAPI suggests the author expects personal-scale use.

One more boundary: the README describes the author's CORSAPI as being for testing only. Pointing a production client at pz.v88.qzz.io is exactly the case the README warns against. Deploy your own Worker and set prefix to it.

## Where this sits next to LibreTV and other MoonTV source projects

The related searches around this repository are mostly other projects: LibreTV, OrionTV, KatelyaTV, KVideo, Moontv plus. The meaningful comparison is with LibreTV, because the split is architectural rather than cosmetic. LibreTV is an application you deploy and which resolves sources itself. LunaTV-config is the opposite arrangement: the source list and the prefix rewriting live outside the client, and the client receives an already-processed subscription string. That means you can change sources without touching the client, and you can route every API call through one Worker you control. It also means the client is useless without that URL, and that a broken Worker breaks every device at once. If your requirement is a self-contained deployment with no external subscription endpoint, this repository's model is the wrong shape for you. If your requirement is to swap sources and control the egress point centrally, it fits.

## Updating the list and what maintenance costs you

The repository layout tells you how the list is maintained. check_api.js tests the APIs, update_readme.js regenerates the README, and report.md holds the result. The README says the configuration sources come from GitHub and are updated periodically, and that the Worker caches for 7200 seconds. So an upstream source dying shows up as a failed entry in the next check, and your Worker keeps serving the cached copy until the cache expires.

The last push to the repository was on 2026-09-22, so the list is being touched. That says nothing about whether any individual API in the 88-entry full list still works, and the README does not promise that. Your own upgrade cost is small if you deploy the Worker as a copy of _worker.js: you re-paste the file when you want a change. If you fork and edit JSON_SOURCES to point at your own source files, you take over the checking job that check_api.js currently does, and nothing in the README describes how to run it or what its output looks like. That is the point where this stops being a copy-and-paste deployment.

## Conclusion

Adopt this if you already run MoonTV or LunaTV and want a ready-made source list with a self-hosted Worker in front of it, and you are willing to deploy that Worker yourself and keep an eye on dead APIs. Do not adopt it if you want a maintained application, a licence you can read before shipping, or a proxy you are allowed to point production traffic at: the README describes the author's own CORSAPI as test use only and asks people not to abuse it. Verify first that your client accepts Base58 subscription links, that format=3 with your own prefix resolves, and that the upstream source files still return the resource counts the README lists (31, 61 and 88).

## FAQ

### What is hafrey1/LunaTV-config, and do I need MoonTV or LunaTV to use it?

It is a set of MoonTV/LunaTV source configurations plus a Cloudflare Worker that proxies API requests and emits Base58 subscription links. The README assumes an existing client that accepts a subscription URL, so it is not useful on its own.

### How do I install hafrey1/LunaTV-config and get a subscription link?

Copy the contents of _worker.js into a Cloudflare Worker created from the Hello World template, or upload it as a Pages project, then save and deploy. After that the README's recommended subscription form is your Worker URL with format=3 and one of source=jin18, source=jingjian or source=full.

### What is the difference between jin18, jingjian and full in LunaTV-config?

The README lists jin18 as 31 resources with no adult content, jingjian as 61 resources with adult content, and full as 88 resources with adult content, which is the default when source is omitted.

### Why does my LunaTV-config Worker request return an error instead of JSON?

The README sets a default request timeout of 9 seconds, and a request that exceeds it returns an error message rather than the configuration. The README documents an errors&limit=10 parameter for reading the error log, but does not state where that log is stored.

## Sources

- [hafrey1/LunaTV-config on GitHub](https://github.com/hafrey1/LunaTV-config)
- [Issues](https://github.com/hafrey1/LunaTV-config/issues)
- [Project website](https://pz.v88.qzz.io)
- [README](https://github.com/hafrey1/LunaTV-config/blob/main/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/hafrey1-lunatv-config
