shithub: nvi

ref: b7306bef352fc0796d84a5ef0bd5a301629adfe9
dir: /peertube.c/

View raw version
#include <u.h>
#include <libc.h>
#include <json.h>
#include "nvi.h"

static int
addfmt(Info *i, JSON *f)
{
	JSON *x, *j;
	Format *fmt;
	char *s, *t;
	JSONEl *e;
	int fd, n;

	j = nil;
	if((x = jfield(f, JSONString, "metadataUrl", nil)) == nil){
		werrstr("no metadataUrl");
		goto err;
	}
	j = nil;
	if((fd = hget(jsonstr(x), -1)) >= 0){
		if((s = readall(fd)) != nil){
			j = jsonparse(s);
			free(s);
		}
		close(fd);
	}
	procwait();
	if(j == nil)
		goto err;

	if((x = jfield(f, JSONString, "fileDownloadUrl", nil)) == nil){
		werrstr("no fileDownloadUrl");
		goto err;
	}
	i->nfmt++;
	if((i->fmt = realloc(i->fmt, i->nfmt * sizeof(*fmt))) == nil)
		sysfatal("memory");
	fmt = &i->fmt[i->nfmt - 1];
	memset(fmt, 0, sizeof(*fmt));
	fmt->url = estrdup(jsonstr(x));
	if((x = jsonbyname(f, "size")) != nil)
		fmt->sz = x->n;

	s = strdup("");
	if((x = jfield(j, JSONArray, "streams", nil)) != nil){
		for(e = x->first; e != nil; e = e->next){
			if((x = jfield(e->val, JSONString, "codec_name", nil)) != nil){
				t = smprint("%s%s%s", s, *s ? "," : "", jsonstr(x));
				free(s);
				s = t;
			}
			if((x = jfield(e->val, JSONString, "codec_type", nil)) != nil){
				t = jsonstr(x);
				if(strcmp(t, "video") == 0)
					fmt->included |= Ivideo;
				else if(strcmp(t, "audio") == 0){
					fmt->included |= Iaudio;
					if((n = jint(e->val, "sample_rate")) != 0){
						t = smprint("%s,rate=%d", s, n);
						free(s);
						s = t;
					}
					if((n = jint(e->val, "channels")) != 0){
						t = smprint("%s,channels=%d", s, n);
						free(s);
						s = t;
					}
				}
			}else{
				werrstr("codec_type missing");
				goto err;
			}
		}
	}
	fmt->type = s;
	jsonfree(j);

	if((x = jfield(f, JSONObject, "resolution", nil)) != nil){
		fmt->id = jint(x, "id");
		if((s = jsonstr(jfield(x, JSONString, "label", nil))) != nil && *s != '0')
			fmt->quality = jstrdup(x, "label");
	}

	return 0;
err:
	werrstr("addfmt: %r");
	jsonfree(j);
	return -1;
}

Info *
peertube(char *url)
{
	int fd, peertube;
	char *s, *o, *id;
	JSONEl *e, *f;
	JSON *j, *z;
	Info *i;

	peertube = 0;
	i = nil;
	if((fd = hget(url, -1)) >= 0){
		if((s = readall(fd)) != nil){
			if((o = strstr(s, "property=\"og:platform\"")) != nil && strstr(o+23, "content=\"PeerTube\"") != nil)
				peertube = 1;
			free(s);
		}
		close(fd);
	}
	procwait();
	if(!peertube){
		if(fd >= 0)
			werrstr("not peertube");
		return nil;
	}

	if((id = strrchr(url, '/')) == nil || (s = strstr(url, "://")) == nil || (s = strchr(s+3, '/')) == nil){
		werrstr("bad url");
		return nil;
	}
	url = smprint("%.*s/api/v1/videos%s", (int)(s-url), url, id);
	fd = hget(url, -1);
	free(url);

	j = nil;
	if(fd >= 0){
		if((s = readall(fd)) != nil){
			j = jsonparse(s);
			free(s);
		}
		close(fd);
	}
	procwait();
	if(j == nil)
		goto err;

	if((i = calloc(1, sizeof(*i))) == nil)
		sysfatal("memory");

	i->author = estrdup(jsonstr(jfield(j, JSONString, "account", "displayName", nil)));
	i->title = jstrdup(j, "name");
	i->description = jstrdup(j, "description");
	i->duration = jint(j, "duration");
	if((s = jsonstr(jsonbyname(j, "publishedAt"))) != nil)
		tmparse(&i->published, "YYYY-MM-DDThh:mm:ss.ttt", s, nil, nil);

	if((z = jfield(j, JSONArray, "files", nil)) != nil){
		for(f = z->first; f != nil; f = f->next){
			if(addfmt(i, f->val) != 0)
				goto err;
		}
	}

	if((z = jfield(j, JSONArray, "streamingPlaylists", nil)) != nil){
		for(e = z->first; e != nil; e = e->next){
			if((z = jfield(e->val, JSONArray, "files", nil)) != nil){
				for(f = z->first; f != nil; f = f->next){
					if(addfmt(i, f->val) != 0)
						goto err;
				}
			}
		}
	}

	jsonfree(j);

	return i;
err:
	werrstr("peertube: %r");
	free(i);
	return nil;
}