Import miniabs 1.0 source

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
xockoandClaude Opus 5.5 committed 2026-10-14 19:26:04 +02:00
commit 4fe9eed870
78 files changed
+5800

No files matched your search

+95
View File
@@ -0,0 +1,95 @@
package com.miniabs;
import org.json.JSONException;
import org.json.JSONObject;
/** One podcast episode, trimmed down to what MiniABS needs. */
final class Episode {
String itemId = ""; // library item (the podcast) id
String id = ""; // episode id
String title = "";
String show = ""; // podcast title
String author = "";
String desc = "";
String ino = ""; // audio file inode, used for downloads
String ext = ".mp3";
String mime = "";
long published; // ms since epoch
double duration; // seconds
long size; // bytes
/** Builds an episode from an Audiobookshelf episode object. Returns null if it has no audio. */
static Episode fromApi(JSONObject e, String itemId, String show, String author) {
if (e == null) return null;
Episode ep = new Episode();
ep.id = Util.str(e, "id");
ep.itemId = itemId != null && itemId.length() > 0 ? itemId : Util.str(e, "libraryItemId");
ep.title = Util.str(e, "title");
ep.show = show == null ? "" : show;
ep.author = author == null ? "" : author;
ep.desc = Util.str(e, "description");
if (ep.desc.length() == 0) ep.desc = Util.str(e, "subtitle");
ep.published = e.optLong("publishedAt", 0);
JSONObject af = e.optJSONObject("audioFile");
if (af != null) {
ep.duration = af.optDouble("duration", 0);
ep.ino = Util.str(af, "ino");
ep.mime = Util.str(af, "mimeType");
JSONObject meta = af.optJSONObject("metadata");
if (meta != null) {
String x = Util.str(meta, "ext");
if (x.length() > 0) ep.ext = x;
ep.size = meta.optLong("size", 0);
}
}
if (ep.duration <= 0) ep.duration = e.optDouble("duration", 0);
if (ep.id.length() == 0 || ep.itemId.length() == 0 || af == null) return null;
ep.ext = safeExt(ep.ext);
// The podcast object (when the API sends it) carries the show name
JSONObject pod = e.optJSONObject("podcast");
if (pod != null && ep.show.length() == 0) {
JSONObject md = pod.optJSONObject("metadata");
if (md != null) {
ep.show = Util.str(md, "title");
ep.author = Util.str(md, "author");
}
}
return ep;
}
private static String safeExt(String x) {
x = x.toLowerCase();
if (!x.startsWith(".")) x = "." + x;
if (!x.matches("\\.[a-z0-9]{1,5}")) x = ".mp3";
return x;
}
JSONObject toJson() {
JSONObject o = new JSONObject();
try {
o.put("itemId", itemId).put("id", id).put("title", title).put("show", show)
.put("author", author).put("desc", desc).put("ino", ino).put("ext", ext)
.put("mime", mime).put("published", published).put("duration", duration)
.put("size", size);
} catch (JSONException ignored) {
}
return o;
}
static Episode fromStored(JSONObject o) {
Episode e = new Episode();
e.itemId = Util.str(o, "itemId");
e.id = Util.str(o, "id");
e.title = Util.str(o, "title");
e.show = Util.str(o, "show");
e.author = Util.str(o, "author");
e.desc = Util.str(o, "desc");
e.ino = Util.str(o, "ino");
e.ext = safeExt(o.optString("ext", ".mp3"));
e.mime = Util.str(o, "mime");
e.published = o.optLong("published", 0);
e.duration = o.optDouble("duration", 0);
e.size = o.optLong("size", 0);
return e;
}
}