feat: setup api
This commit is contained in:
parent
0202a7da5f
commit
20c9d107b7
@ -40,8 +40,8 @@ overseer:
|
||||
zap-stream:
|
||||
cost: 16
|
||||
nsec: "nsec1wya428srvpu96n4h78gualaj7wqw4ecgatgja8d5ytdqrxw56r2se440y4"
|
||||
#blossom:
|
||||
# - "http://localhost:8881"
|
||||
blossom:
|
||||
- "http://localhost:8881"
|
||||
relays:
|
||||
- "ws://localhost:7766"
|
||||
database: "mysql://root:root@localhost:3368/zap_stream?max_connections=2"
|
||||
|
@ -6,6 +6,7 @@ use http_body_util::{BodyExt, Full, StreamBody};
|
||||
use hyper::body::{Frame, Incoming};
|
||||
use hyper::service::Service;
|
||||
use hyper::{Method, Request, Response};
|
||||
use log::error;
|
||||
use std::future::Future;
|
||||
use std::path::PathBuf;
|
||||
use std::pin::Pin;
|
||||
@ -83,7 +84,10 @@ impl Service<Request<Incoming>> for HttpServer {
|
||||
Box::pin(async move {
|
||||
match overseer.api(req).await {
|
||||
Ok(res) => Ok(res),
|
||||
Err(e) => Err(e),
|
||||
Err(e) => {
|
||||
error!("{}", e);
|
||||
Ok(Response::builder().status(500).body(BoxBody::default())?)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -8,6 +8,8 @@ use crate::settings::LndSettings;
|
||||
use crate::variant::StreamMapping;
|
||||
use anyhow::{anyhow, bail, Result};
|
||||
use async_trait::async_trait;
|
||||
use base64::alphabet::STANDARD;
|
||||
use base64::Engine;
|
||||
use bytes::Bytes;
|
||||
use chrono::Utc;
|
||||
use fedimint_tonic_lnd::verrpc::VersionRequest;
|
||||
@ -23,6 +25,7 @@ use log::{error, info, warn};
|
||||
use nostr_sdk::bitcoin::PrivateKey;
|
||||
use nostr_sdk::prelude::Coordinate;
|
||||
use nostr_sdk::{Client, Event, EventBuilder, JsonUtil, Keys, Kind, Tag, ToBech32};
|
||||
use serde::Serialize;
|
||||
use std::collections::HashSet;
|
||||
use std::env::temp_dir;
|
||||
use std::fs::create_dir_all;
|
||||
@ -35,7 +38,7 @@ use uuid::Uuid;
|
||||
use zap_stream_db::sqlx::Encode;
|
||||
use zap_stream_db::{UserStream, UserStreamState, ZapStreamDb};
|
||||
|
||||
const STREAM_EVENT_KIND: u16 = 30_311;
|
||||
const STREAM_EVENT_KIND: u16 = 30_313;
|
||||
|
||||
/// zap.stream NIP-53 overseer
|
||||
pub struct ZapStreamOverseer {
|
||||
@ -184,21 +187,19 @@ impl ZapStreamOverseer {
|
||||
}
|
||||
|
||||
async fn publish_stream_event(&self, stream: &UserStream, pubkey: &Vec<u8>) -> Result<Event> {
|
||||
let mut extra_tags = vec![
|
||||
let extra_tags = vec![
|
||||
Tag::parse(&["p", hex::encode(pubkey).as_str(), "", "host"])?,
|
||||
Tag::parse(&[
|
||||
"streaming",
|
||||
self.map_to_public_url(stream, "live.m3u8")?.as_str(),
|
||||
self.map_to_stream_public_url(stream, "live.m3u8")?.as_str(),
|
||||
])?,
|
||||
Tag::parse(&[
|
||||
"image",
|
||||
self.map_to_public_url(stream, "thumb.webp")?.as_str(),
|
||||
self.map_to_stream_public_url(stream, "thumb.webp")?
|
||||
.as_str(),
|
||||
])?,
|
||||
Tag::parse(&["service", self.map_to_public_url("api/v1")?.as_str()])?,
|
||||
];
|
||||
// flag NIP94 streaming when using blossom servers
|
||||
if self.blossom_servers.len() > 0 {
|
||||
extra_tags.push(Tag::parse(&["streaming", "nip94"])?);
|
||||
}
|
||||
let ev = self
|
||||
.stream_to_event_builder(stream)?
|
||||
.add_tags(extra_tags)
|
||||
@ -207,29 +208,93 @@ impl ZapStreamOverseer {
|
||||
Ok(ev)
|
||||
}
|
||||
|
||||
fn map_to_public_url<'a>(
|
||||
fn map_to_stream_public_url(
|
||||
&self,
|
||||
stream: &UserStream,
|
||||
path: impl Into<&'a str>,
|
||||
path: &str,
|
||||
) -> Result<String> {
|
||||
self.map_to_public_url(&format!("{}/{}", stream.id, path))
|
||||
}
|
||||
|
||||
fn map_to_public_url(&self, path: &str) -> Result<String> {
|
||||
let u: Url = self.public_url.parse()?;
|
||||
Ok(u.join(&format!("/{}/", stream.id))?
|
||||
.join(path.into())?
|
||||
.to_string())
|
||||
Ok(u.join(path)?.to_string())
|
||||
}
|
||||
|
||||
fn check_nip98_auth(&self, req: Request<Incoming>) -> Result<()> {
|
||||
let auth = if let Some(a) = req.headers().get("authorization") {
|
||||
a.to_str()?
|
||||
} else {
|
||||
bail!("Authorization header missing");
|
||||
};
|
||||
|
||||
if !auth.starts_with("Nostr ") {
|
||||
bail!("Invalid authorization scheme");
|
||||
}
|
||||
|
||||
let json = String::from_utf8(
|
||||
base64::engine::general_purpose::STANDARD.decode(auth[6..].as_bytes())?,
|
||||
)?;
|
||||
info!("{}", json);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct Endpoint {}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct AccountInfo {
|
||||
pub endpoints: Vec<Endpoint>,
|
||||
pub event: Event,
|
||||
pub balance: u64,
|
||||
}
|
||||
#[async_trait]
|
||||
impl Overseer for ZapStreamOverseer {
|
||||
async fn api(&self, req: Request<Incoming>) -> Result<Response<BoxBody<Bytes, anyhow::Error>>> {
|
||||
let base = Response::builder()
|
||||
.header("server", "zap-stream-core")
|
||||
.header("access-control-allow-origin", "*")
|
||||
.header("access-control-allow-headers", "*")
|
||||
.header("access-control-allow-methods", "HEAD, GET");
|
||||
|
||||
Ok(match (req.method(), req.uri().path()) {
|
||||
(&Method::GET, "/api/v1/account") => {
|
||||
self.check_nip98_auth(req)?;
|
||||
base.body(Default::default())?
|
||||
}
|
||||
(&Method::PATCH, "/api/v1/account") => {
|
||||
bail!("Not implemented")
|
||||
}
|
||||
_ => Response::builder()
|
||||
.header("server", "zap-stream-core")
|
||||
.status(404)
|
||||
.body(Full::from("").map_err(anyhow::Error::new).boxed())?,
|
||||
(&Method::GET, "/api/v1/topup") => {
|
||||
bail!("Not implemented")
|
||||
}
|
||||
(&Method::PATCH, "/api/v1/event") => {
|
||||
bail!("Not implemented")
|
||||
}
|
||||
(&Method::POST, "/api/v1/withdraw") => {
|
||||
bail!("Not implemented")
|
||||
}
|
||||
(&Method::POST, "/api/v1/account/forward") => {
|
||||
bail!("Not implemented")
|
||||
}
|
||||
(&Method::DELETE, "/api/v1/account/forward/<id>") => {
|
||||
bail!("Not implemented")
|
||||
}
|
||||
(&Method::GET, "/api/v1/account/history") => {
|
||||
bail!("Not implemented")
|
||||
}
|
||||
(&Method::GET, "/api/v1/account/keys") => {
|
||||
bail!("Not implemented")
|
||||
}
|
||||
_ => {
|
||||
if req.method() == Method::OPTIONS {
|
||||
base.body(Default::default())?
|
||||
} else {
|
||||
base.status(404).body(Default::default())?
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user