mirror of
https://github.com/m1k1o/neko.git
synced 2024-07-24 14:40:50 +12:00
Merge branch 'master' of github.com:m1k1o/neko into sk_lang
This commit is contained in:
commit
1ce276f313
@ -1,160 +1,4 @@
|
||||
FROM debian:stretch-slim
|
||||
|
||||
#
|
||||
# cluster fuck of packages for neko, node, go and gstreamer
|
||||
RUN set -eux; apt-get update; apt-get install -y --no-install-recommends \
|
||||
autoconf ca-certificates curl netbase wget \
|
||||
bzr git mercurial openssh-client subversion procps cmake automake bzip2 dpkg-dev file g++ gcc \
|
||||
libbz2-dev libc6-dev libcurl4-openssl-dev libdb-dev libevent-dev libffi-dev libgdbm-dev libglib2.0-dev libgmp-dev \
|
||||
libjpeg-dev libkrb5-dev liblzma-dev libmagickcore-dev libmagickwand-dev libmaxminddb-dev libncurses5-dev libncursesw5-dev \
|
||||
libpng-dev libpq-dev libreadline-dev libsqlite3-dev libssl-dev libtool libwebp-dev libxml2-dev libxslt-dev libyaml-dev \
|
||||
make patch unzip xz-utils zlib1g-dev pkg-config \
|
||||
build-essential perl python autopoint bison flex \
|
||||
gettext openssl libopus-dev libvpx-dev libpulse-dev libx11-dev libxv-dev libxt-dev libxrandr-dev \
|
||||
libxfixes-dev apt-utils x11vnc libxtst-dev dialog \
|
||||
pulseaudio openbox chromium firefox-esr dbus-x11 xserver-xorg-video-dummy supervisor; \
|
||||
if ! command -v gpg > /dev/null; then \
|
||||
apt-get install -y --no-install-recommends gnupg dirmngr; \
|
||||
fi
|
||||
|
||||
#
|
||||
# Install libclipboard
|
||||
RUN set -eux; \
|
||||
cd /tmp ; \
|
||||
git clone https://github.com/jtanx/libclipboard ; \
|
||||
cd libclipboard ; \
|
||||
cmake . ; \
|
||||
make -j4; \
|
||||
make install; \
|
||||
rm -rf /tmp/libclipboard
|
||||
|
||||
#
|
||||
# Set up env for gst
|
||||
ENV PATH=/gst/local/bin:$PATH
|
||||
ENV LD_LIBRARY_PATH=/gst/local/lib:$LD_LIBRARY_PATH
|
||||
ENV PKG_CONFIG_PATH=/gst/local/lib/pkgconfig:$PKG_CONFIG_PATH
|
||||
|
||||
#
|
||||
# Add node
|
||||
ENV NODE_VERSION 12.14.1
|
||||
RUN set -eux; \
|
||||
ARCH= ; dpkgArch="$(dpkg --print-architecture)" \
|
||||
;case "${dpkgArch##*-}" in \
|
||||
amd64) ARCH='x64';; \
|
||||
ppc64el) ARCH='ppc64le';; \
|
||||
s390x) ARCH='s390x';; \
|
||||
arm64) ARCH='arm64';; \
|
||||
armhf) ARCH='armv7l';; \
|
||||
i386) ARCH='x86';; \
|
||||
*) echo "unsupported architecture"; exit 1 ;; \
|
||||
esac;\
|
||||
# gpg keys listed at https://github.com/nodejs/node#release-keys
|
||||
for key in \
|
||||
94AE36675C464D64BAFA68DD7434390BDBE9B9C5 \
|
||||
FD3A5288F042B6850C66B31F09FE44734EB7990E \
|
||||
71DCFD284A79C3B38668286BC97EC7A07EDE3FC1 \
|
||||
DD8F2338BAE7501E3DD5AC78C273792F7D83545D \
|
||||
C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 \
|
||||
B9AE9905FFD7803F25714661B63B535A4C206CA9 \
|
||||
77984A986EBC2AA786BC0F66B01FBB92821C587A \
|
||||
8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \
|
||||
4ED778F539E3634C779C87C6D7062848A1AB005C \
|
||||
A48C2BEE680E841632CD4E44F07496B3EB3C1762 \
|
||||
B9E2F5981AA6E0CD28160D9FF13993A75599653C \
|
||||
; do \
|
||||
gpg --batch --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys "$key" || \
|
||||
gpg --batch --keyserver hkp://ipv4.pool.sks-keyservers.net --recv-keys "$key" || \
|
||||
gpg --batch --keyserver hkp://pgp.mit.edu:80 --recv-keys "$key"; \
|
||||
done; \
|
||||
curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH.tar.xz"; \
|
||||
curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc"; \
|
||||
gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc; \
|
||||
grep " node-v$NODE_VERSION-linux-$ARCH.tar.xz\$" SHASUMS256.txt | sha256sum -c - ; \
|
||||
tar -xJf "node-v$NODE_VERSION-linux-$ARCH.tar.xz" -C /usr/local --strip-components=1 --no-same-owner; \
|
||||
rm "node-v$NODE_VERSION-linux-$ARCH.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt; \
|
||||
ln -s /usr/local/bin/node /usr/local/bin/nodejs
|
||||
|
||||
#
|
||||
# Add golang
|
||||
ENV GOLANG_VERSION 1.14.1
|
||||
RUN set -eux; \
|
||||
dpkgArch="$(dpkg --print-architecture)"; \
|
||||
case "${dpkgArch##*-}" in \
|
||||
amd64) goRelArch='linux-amd64'; goRelSha256='2f49eb17ce8b48c680cdb166ffd7389702c0dec6effa090c324804a5cac8a7f8' ;; \
|
||||
armhf) goRelArch='linux-armv6l'; goRelSha256='04f10e345dae0d7c6c32ffd6356b47f2d4d0e8a0cb757f4ef48ead6c5bef206f' ;; \
|
||||
arm64) goRelArch='linux-arm64'; goRelSha256='5d8f2c202f35481617e24e63cca30c6afb1ec2585006c4a6ecf16c5f4928ab3c' ;; \
|
||||
i386) goRelArch='linux-386'; goRelSha256='92d465accdebbe2d0749b2f90c22ecb1fd2492435144923f88ce410cd56b6546' ;; \
|
||||
ppc64el) goRelArch='linux-ppc64le'; goRelSha256='6559201d452ee2782dfd684d59c05e3ecf789dc40a7ec0ad9ae2dd9f489c0fe1' ;; \
|
||||
s390x) goRelArch='linux-s390x'; goRelSha256='af009bd6e7729c441fec78af427743fefbf11f919c562e01b37836d835f74226' ;; \
|
||||
*) goRelArch='src'; goRelSha256='2ad2572115b0d1b4cb4c138e6b3a31cee6294cb48af75ee86bec3dca04507676'; \
|
||||
echo >&2; echo >&2 "warning: current architecture ($dpkgArch) does not have a corresponding Go binary release; will be building from source"; echo >&2 ;; \
|
||||
esac; \
|
||||
url="https://golang.org/dl/go${GOLANG_VERSION}.${goRelArch}.tar.gz"; \
|
||||
wget -O go.tgz "$url"; \
|
||||
echo "${goRelSha256} *go.tgz" | sha256sum -c -; \
|
||||
tar -C /usr/local -xzf go.tgz; \
|
||||
rm go.tgz; \
|
||||
if [ "$goRelArch" = 'src' ]; then \
|
||||
echo >&2; \
|
||||
echo >&2 'error: UNIMPLEMENTED'; \
|
||||
echo >&2 'TODO install golang-any from jessie-backports for GOROOT_BOOTSTRAP (and uninstall after build)'; \
|
||||
echo >&2; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
export PATH="/usr/local/go/bin:$PATH"; \
|
||||
go version
|
||||
|
||||
ENV GOPATH /go
|
||||
ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH
|
||||
|
||||
#
|
||||
# Install Go tools w/module support
|
||||
RUN mkdir -p /tmp/gotools \
|
||||
&& cd /tmp/gotools \
|
||||
&& GOPATH=/tmp/gotools GO111MODULE=on go get -v golang.org/x/tools/gopls@latest 2>&1 \
|
||||
&& GOPATH=/tmp/gotools GO111MODULE=on go get -v \
|
||||
honnef.co/go/tools/...@latest \
|
||||
golang.org/x/tools/cmd/gorename@latest \
|
||||
golang.org/x/tools/cmd/goimports@latest \
|
||||
golang.org/x/tools/cmd/guru@latest \
|
||||
golang.org/x/lint/golint@latest \
|
||||
github.com/mdempsky/gocode@latest \
|
||||
github.com/cweill/gotests/...@latest \
|
||||
github.com/haya14busa/goplay/cmd/goplay@latest \
|
||||
github.com/sqs/goreturns@latest \
|
||||
github.com/josharian/impl@latest \
|
||||
github.com/davidrjenni/reftools/cmd/fillstruct@latest \
|
||||
github.com/uudashr/gopkgs/v2/cmd/gopkgs@latest \
|
||||
github.com/ramya-rao-a/go-outline@latest \
|
||||
github.com/acroca/go-symbols@latest \
|
||||
github.com/godoctor/godoctor@latest \
|
||||
github.com/rogpeppe/godef@latest \
|
||||
github.com/zmb3/gogetdoc@latest \
|
||||
github.com/fatih/gomodifytags@latest \
|
||||
github.com/mgechev/revive@latest \
|
||||
github.com/go-delve/delve/cmd/dlv@latest 2>&1 \
|
||||
#
|
||||
# Build Go tools w/o module support
|
||||
&& GOPATH=/tmp/gotools go get -v github.com/alecthomas/gometalinter 2>&1 \
|
||||
#
|
||||
# Build gocode-gomod
|
||||
&& GOPATH=/tmp/gotools go get -x -d github.com/stamblerre/gocode 2>&1 \
|
||||
&& GOPATH=/tmp/gotools go build -o gocode-gomod github.com/stamblerre/gocode \
|
||||
#
|
||||
# Install Go tools
|
||||
&& mv /tmp/gotools/bin/* /usr/local/bin/ \
|
||||
&& mv gocode-gomod /usr/local/bin/ \
|
||||
#
|
||||
# Install golangci-lint
|
||||
&& curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b /usr/local/bin 2>&1 \
|
||||
#
|
||||
# Setup paths
|
||||
&& mkdir -p "$GOPATH/src" "$GOPATH/bin" "$GOPATH/pkg/mod" \
|
||||
&& chmod -R 777 "$GOPATH"
|
||||
|
||||
#
|
||||
# Turn on go modules
|
||||
ENV GO111MODULE=on
|
||||
FROM nurdism/neko:dev
|
||||
|
||||
# Use the "remoteUser" property in devcontainer.json to use it. On Linux, the container
|
||||
# user's GID/UIDs will be updated to match your local UID/GID (when using the dockerFile property).
|
||||
|
@ -7,7 +7,8 @@
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )/.."
|
||||
|
||||
build_gst() {
|
||||
if [ ! -d /gst ]; then
|
||||
if [ ! -L /gst || ! -d /gst ]; then
|
||||
sudo rm -rf /gst;
|
||||
sudo mkdir -p /workspace/.build/gst
|
||||
sudo ln -s /workspace/.build/gst /gst
|
||||
sudo chown -R neko /workspace/.build
|
||||
@ -39,23 +40,33 @@ build_gst() {
|
||||
done'
|
||||
}
|
||||
|
||||
build_dev() {
|
||||
set -eux; \
|
||||
sudo docker build -f files/dev/Dockerfile -t nurdism/neko:dev $DIR ; \
|
||||
sudo docker push nurdism/neko:dev;
|
||||
}
|
||||
|
||||
build_deps() {
|
||||
set -eux; \
|
||||
sudo docker build -f files/deps/Dockerfile -t nurdism/neko:deps $DIR ; \
|
||||
sudo docker push nurdism/neko:deps;
|
||||
}
|
||||
|
||||
build_base() {
|
||||
set -eux; \
|
||||
cd $DIR/server; go get; ./build; \
|
||||
cd $DIR/server; go get -v -t -d . ; ./build; \
|
||||
cd $DIR/client; npm install; npm run build; \
|
||||
cd $DIR; sudo docker build -f Dockerfile -t nurdism/neko:base . ;
|
||||
cd $DIR; sudo docker build -f .docker/files/base/Dockerfile -t nurdism/neko:base $DIR ;
|
||||
}
|
||||
|
||||
build_firefox() {
|
||||
set -eux; \
|
||||
cd $DIR/.docker/files/firefox; \
|
||||
sudo docker build -f Dockerfile -t nurdism/neko:firefox -t nurdism/neko:latest . ;
|
||||
sudo docker build -f files/firefox/Dockerfile -t nurdism/neko:firefox -t nurdism/neko:latest $DIR ;
|
||||
}
|
||||
|
||||
build_chromium() {
|
||||
set -eux; \
|
||||
cd $DIR/.docker/files/chromium; \
|
||||
sudo docker build -f Dockerfile -t nurdism/neko:chromium . ;
|
||||
sudo docker build -f files/chromium/Dockerfile -t nurdism/neko:chromium $DIR ;
|
||||
}
|
||||
|
||||
build_docker() {
|
||||
@ -82,6 +93,9 @@ set -ex
|
||||
case $1 in
|
||||
push) build_push ;;
|
||||
docker) build_docker ;;
|
||||
base) build_base ;;
|
||||
deps) build_deps ;;
|
||||
dev) build_dev ;;
|
||||
gst) build_gst ;;
|
||||
*) build_docker ;;
|
||||
esac
|
||||
|
@ -1,4 +1,4 @@
|
||||
FROM debian:stretch-slim
|
||||
FROM nurdism/neko:deps
|
||||
|
||||
#
|
||||
# avoid warnings by switching to noninteractive
|
||||
@ -11,8 +11,7 @@ ARG USER_GID=$USER_UID
|
||||
#
|
||||
# install neko dependencies
|
||||
RUN set -eux; apt-get update; \
|
||||
apt-get install -y --no-install-recommends wget ca-certificates pulseaudio openbox dbus-x11 xserver-xorg-video-dummy supervisor; \
|
||||
apt-get install -y --no-install-recommends libcairo2 libxcb1 libxrandr2 libxv1 libopus0 libvpx4; \
|
||||
apt-get install -y --no-install-recommends wget ca-certificates; \
|
||||
#
|
||||
# create a non-root user
|
||||
groupadd --gid $USER_GID $USERNAME; \
|
||||
@ -36,41 +35,28 @@ RUN set -eux; apt-get update; \
|
||||
apt-get clean -y; \
|
||||
rm -rf /var/lib/apt/lists/* /var/cache/apt/*
|
||||
|
||||
#
|
||||
# add gst to env
|
||||
ENV PATH=/gst/local/bin:$PATH
|
||||
ENV LD_LIBRARY_PATH=/gst/local/lib:$LD_LIBRARY_PATH
|
||||
ENV PKG_CONFIG_PATH=/gst/local/lib/pkgconfig:$PKG_CONFIG_PATH
|
||||
|
||||
#
|
||||
# copy gst
|
||||
COPY .build/gst/local /gst/local/
|
||||
|
||||
#
|
||||
# env
|
||||
ENV USER=$USERNAME
|
||||
ENV DISPLAY=:99.0
|
||||
|
||||
#
|
||||
# copy configuation files
|
||||
COPY .docker/files/dbus /usr/bin/dbus
|
||||
COPY .docker/files/openbox.xml /etc/neko/openbox.xml
|
||||
COPY .docker/files/neko/supervisord.conf /etc/neko/supervisord/neko.conf
|
||||
COPY .docker/files/supervisord.conf /etc/neko/supervisord.conf
|
||||
COPY .docker/files/xorg.conf /etc/neko/xorg.conf
|
||||
COPY .docker/files/default.pa /etc/pulse/default.pa
|
||||
|
||||
#
|
||||
# neko files
|
||||
COPY client/dist/ /var/www
|
||||
COPY server/bin/neko /usr/bin/neko
|
||||
|
||||
#
|
||||
# neko env
|
||||
ENV NEKO_PASSWORD=neko
|
||||
ENV NEKO_PASSWORD_ADMIN=admin
|
||||
ENV NEKO_BIND=:8080
|
||||
|
||||
#
|
||||
# neko config
|
||||
COPY .docker/files/dbus /usr/bin/dbus
|
||||
COPY .docker/files/openbox.xml /etc/neko/openbox.xml
|
||||
COPY .docker/files/supervisord.conf /etc/neko/supervisord.conf
|
||||
COPY .docker/files/xorg.conf /etc/neko/xorg.conf
|
||||
COPY .docker/files/default.pa /etc/pulse/default.pa
|
||||
COPY .docker/files/neko/supervisord.conf /etc/neko/supervisord/neko.conf
|
||||
|
||||
#
|
||||
# neko dist
|
||||
COPY client/dist/ /var/www
|
||||
COPY server/bin/neko /usr/bin/neko
|
||||
|
||||
#
|
||||
# run neko
|
||||
CMD ["/usr/bin/supervisord", "-c", "/etc/neko/supervisord.conf"]
|
@ -19,6 +19,6 @@ RUN set -eux; apt-get update; \
|
||||
|
||||
#
|
||||
# copy configuation files
|
||||
COPY supervisord.conf /etc/neko/supervisord/chromium.conf
|
||||
COPY preferences.json /usr/share/chromium/master_preferences
|
||||
COPY policies.json /etc/chromium/policies/managed/policies.json
|
||||
COPY .docker/files/chromium/supervisord.conf /etc/neko/supervisord/chromium.conf
|
||||
COPY .docker/files/chromium/preferences.json /usr/share/chromium/master_preferences
|
||||
COPY .docker/files/chromium/policies.json /etc/chromium/policies/managed/policies.json
|
21
.docker/files/deps/Dockerfile
Normal file
21
.docker/files/deps/Dockerfile
Normal file
@ -0,0 +1,21 @@
|
||||
FROM debian:stretch-slim
|
||||
|
||||
#
|
||||
# install neko dependencies
|
||||
RUN set -eux; apt-get update; \
|
||||
apt-get install -y --no-install-recommends pulseaudio openbox dbus-x11 xserver-xorg-video-dummy supervisor; \
|
||||
apt-get install -y --no-install-recommends libcairo2 libxcb1 libxrandr2 libxv1 libopus0 libvpx4; \
|
||||
#
|
||||
# clean up
|
||||
apt-get clean -y; \
|
||||
rm -rf /var/lib/apt/lists/* /var/cache/apt/*
|
||||
|
||||
#
|
||||
# add gst to env
|
||||
ENV PATH=/gst/local/bin:$PATH
|
||||
ENV LD_LIBRARY_PATH=/gst/local/lib:$LD_LIBRARY_PATH
|
||||
ENV PKG_CONFIG_PATH=/gst/local/lib/pkgconfig:$PKG_CONFIG_PATH
|
||||
|
||||
#
|
||||
# copy gst
|
||||
COPY .build/gst/local /gst/local/
|
191
.docker/files/dev/Dockerfile
Normal file
191
.docker/files/dev/Dockerfile
Normal file
@ -0,0 +1,191 @@
|
||||
FROM debian:stretch-slim
|
||||
|
||||
#
|
||||
# cluster fuck of packages for neko, node, go and gstreamer
|
||||
RUN set -eux; apt-get update; apt-get install -y --no-install-recommends \
|
||||
apt-transport-https gnupg-agent software-properties-common lsb-release \
|
||||
autoconf ca-certificates curl netbase wget gnupg dirmngr libatomic1 \
|
||||
libghc-zlib-dev libexpat1-dev \
|
||||
bzr mercurial openssh-client subversion procps cmake automake bzip2 dpkg-dev file g++ gcc \
|
||||
libbz2-dev libc6-dev libcurl4-openssl-dev libdb-dev libevent-dev libffi-dev libgdbm-dev libglib2.0-dev libgmp-dev \
|
||||
libjpeg-dev libkrb5-dev liblzma-dev libmagickcore-dev libmagickwand-dev libmaxminddb-dev libncurses5-dev libncursesw5-dev \
|
||||
libpng-dev libpq-dev libreadline-dev libsqlite3-dev libssl-dev libtool libwebp-dev libxml2-dev libxslt-dev libyaml-dev \
|
||||
make patch unzip xz-utils zlib1g-dev pkg-config \
|
||||
build-essential perl python autopoint bison flex \
|
||||
gettext openssl libopus-dev libvpx-dev libpulse-dev libx11-dev libxv-dev libxt-dev libxrandr-dev \
|
||||
libxfixes-dev apt-utils x11vnc libxtst-dev dialog \
|
||||
pulseaudio openbox chromium firefox-esr dbus-x11 xserver-xorg-video-dummy supervisor;
|
||||
|
||||
#
|
||||
# add git
|
||||
ENV GIT_VERSION 2.21.0
|
||||
|
||||
RUN set -eux; \
|
||||
cd /tmp/; \
|
||||
wget https://github.com/git/git/archive/v$GIT_VERSION.zip -O latestgit.zip; \
|
||||
unzip latestgit.zip; \
|
||||
cd git-$GIT_VERSION; \
|
||||
make prefix=/usr/local all; \
|
||||
make prefix=/usr/local install; \
|
||||
rm -rf /tmp/latestgit.zip /tmp/git-$GIT_VERSION;
|
||||
|
||||
#
|
||||
# install libclipboard
|
||||
RUN set -eux; \
|
||||
cd /tmp; \
|
||||
git clone https://github.com/jtanx/libclipboard; \
|
||||
cd libclipboard; \
|
||||
cmake . ; \
|
||||
make -j4; \
|
||||
make install; \
|
||||
rm -rf /tmp/libclipboard;
|
||||
|
||||
#
|
||||
# set up env for gst
|
||||
ENV PATH=/gst/local/bin:$PATH
|
||||
ENV LD_LIBRARY_PATH=/gst/local/lib:$LD_LIBRARY_PATH
|
||||
ENV PKG_CONFIG_PATH=/gst/local/lib/pkgconfig:$PKG_CONFIG_PATH
|
||||
|
||||
#
|
||||
# copy gst
|
||||
COPY .build/gst/local /gst/local/
|
||||
|
||||
#
|
||||
# add node
|
||||
ENV NODE_VERSION 12.16.2
|
||||
RUN ARCH= && dpkgArch="$(dpkg --print-architecture)" \
|
||||
&& case "${dpkgArch##*-}" in \
|
||||
amd64) ARCH='x64';; \
|
||||
ppc64el) ARCH='ppc64le';; \
|
||||
s390x) ARCH='s390x';; \
|
||||
arm64) ARCH='arm64';; \
|
||||
armhf) ARCH='armv7l';; \
|
||||
i386) ARCH='x86';; \
|
||||
*) echo "unsupported architecture"; exit 1 ;; \
|
||||
esac \
|
||||
&& set -ex \
|
||||
&& for key in \
|
||||
94AE36675C464D64BAFA68DD7434390BDBE9B9C5 \
|
||||
FD3A5288F042B6850C66B31F09FE44734EB7990E \
|
||||
71DCFD284A79C3B38668286BC97EC7A07EDE3FC1 \
|
||||
DD8F2338BAE7501E3DD5AC78C273792F7D83545D \
|
||||
C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 \
|
||||
B9AE9905FFD7803F25714661B63B535A4C206CA9 \
|
||||
77984A986EBC2AA786BC0F66B01FBB92821C587A \
|
||||
8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \
|
||||
4ED778F539E3634C779C87C6D7062848A1AB005C \
|
||||
A48C2BEE680E841632CD4E44F07496B3EB3C1762 \
|
||||
B9E2F5981AA6E0CD28160D9FF13993A75599653C \
|
||||
; do \
|
||||
gpg --batch --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys "$key" || \
|
||||
gpg --batch --keyserver hkp://ipv4.pool.sks-keyservers.net --recv-keys "$key" || \
|
||||
gpg --batch --keyserver hkp://pgp.mit.edu:80 --recv-keys "$key" ; \
|
||||
done \
|
||||
&& curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH.tar.xz" \
|
||||
&& curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \
|
||||
&& gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \
|
||||
&& grep " node-v$NODE_VERSION-linux-$ARCH.tar.xz\$" SHASUMS256.txt | sha256sum -c - \
|
||||
&& tar -xJf "node-v$NODE_VERSION-linux-$ARCH.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \
|
||||
&& rm "node-v$NODE_VERSION-linux-$ARCH.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \
|
||||
&& apt-mark auto '.*' > /dev/null \
|
||||
&& find /usr/local -type f -executable -exec ldd '{}' ';' \
|
||||
| awk '/=>/ { print $(NF-1) }' \
|
||||
| sort -u \
|
||||
| xargs -r dpkg-query --search \
|
||||
| cut -d: -f1 \
|
||||
| sort -u \
|
||||
| xargs -r apt-mark manual \
|
||||
&& ln -s /usr/local/bin/node /usr/local/bin/nodejs \
|
||||
# smoke tests
|
||||
&& node --version \
|
||||
&& npm --version
|
||||
|
||||
#
|
||||
# add golang
|
||||
ENV GOLANG_VERSION 1.14.2
|
||||
RUN set -eux; \
|
||||
dpkgArch="$(dpkg --print-architecture)"; \
|
||||
case "${dpkgArch##*-}" in \
|
||||
amd64) goRelArch='linux-amd64'; goRelSha256='6272d6e940ecb71ea5636ddb5fab3933e087c1356173c61f4a803895e947ebb3' ;; \
|
||||
armhf) goRelArch='linux-armv6l'; goRelSha256='eb4550ba741506c2a4057ea4d3a5ad7ed5a887de67c7232f1e4795464361c83c' ;; \
|
||||
arm64) goRelArch='linux-arm64'; goRelSha256='bb6d22fe5806352c3d0826676654e09b6e41eb1af52e8d506d3fa85adf7f8d88' ;; \
|
||||
i386) goRelArch='linux-386'; goRelSha256='cab5f51e6ffb616c6ee963c3d0650ca4e3c4108307c44f2baf233fcb8ff098f6' ;; \
|
||||
ppc64el) goRelArch='linux-ppc64le'; goRelSha256='48c22268c81ced9084a43bbe2c1596d3e636b5560b30a32434a7f15e561de160' ;; \
|
||||
s390x) goRelArch='linux-s390x'; goRelSha256='501cc919648c9d85b901963303c5061ea6814c80f0d35fda9e62980d3ff58cf4' ;; \
|
||||
*) goRelArch='src'; goRelSha256='98de84e69726a66da7b4e58eac41b99cbe274d7e8906eeb8a5b7eb0aadee7f7c'; \
|
||||
echo >&2; echo >&2 "warning: current architecture ($dpkgArch) does not have a corresponding Go binary release; will be building from source"; echo >&2 ;; \
|
||||
esac; \
|
||||
url="https://golang.org/dl/go${GOLANG_VERSION}.${goRelArch}.tar.gz"; \
|
||||
wget -O go.tgz "$url"; \
|
||||
echo "${goRelSha256} *go.tgz" | sha256sum -c -; \
|
||||
tar -C /usr/local -xzf go.tgz; \
|
||||
rm go.tgz; \
|
||||
if [ "$goRelArch" = 'src' ]; then \
|
||||
echo >&2; \
|
||||
echo >&2 'error: UNIMPLEMENTED'; \
|
||||
echo >&2 'TODO install golang-any from jessie-backports for GOROOT_BOOTSTRAP (and uninstall after build)'; \
|
||||
echo >&2; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
export PATH="/usr/local/go/bin:$PATH"; \
|
||||
go version
|
||||
|
||||
ENV GOPATH /go
|
||||
ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH
|
||||
RUN mkdir -p "$GOPATH/src" "$GOPATH/bin" && chmod -R 777 "$GOPATH"
|
||||
|
||||
#
|
||||
# install Go tools w/module support
|
||||
RUN mkdir -p /tmp/gotools \
|
||||
&& cd /tmp/gotools \
|
||||
&& GOPATH=/tmp/gotools GO111MODULE=on go get -v golang.org/x/tools/gopls@latest 2>&1 \
|
||||
&& GOPATH=/tmp/gotools GO111MODULE=on go get -v \
|
||||
honnef.co/go/tools/...@latest \
|
||||
golang.org/x/tools/cmd/gorename@latest \
|
||||
golang.org/x/tools/cmd/goimports@latest \
|
||||
golang.org/x/tools/cmd/guru@latest \
|
||||
golang.org/x/lint/golint@latest \
|
||||
github.com/mdempsky/gocode@latest \
|
||||
github.com/cweill/gotests/...@latest \
|
||||
github.com/haya14busa/goplay/cmd/goplay@latest \
|
||||
github.com/sqs/goreturns@latest \
|
||||
github.com/josharian/impl@latest \
|
||||
github.com/davidrjenni/reftools/cmd/fillstruct@latest \
|
||||
github.com/uudashr/gopkgs/v2/cmd/gopkgs@latest \
|
||||
github.com/ramya-rao-a/go-outline@latest \
|
||||
github.com/acroca/go-symbols@latest \
|
||||
github.com/godoctor/godoctor@latest \
|
||||
github.com/rogpeppe/godef@latest \
|
||||
github.com/zmb3/gogetdoc@latest \
|
||||
github.com/fatih/gomodifytags@latest \
|
||||
github.com/mgechev/revive@latest \
|
||||
github.com/go-delve/delve/cmd/dlv@latest 2>&1 \
|
||||
#
|
||||
# build Go tools w/o module support
|
||||
&& GOPATH=/tmp/gotools go get -v github.com/alecthomas/gometalinter 2>&1 \
|
||||
#
|
||||
# build gocode-gomod
|
||||
&& GOPATH=/tmp/gotools go get -x -d github.com/stamblerre/gocode 2>&1 \
|
||||
&& GOPATH=/tmp/gotools go build -o gocode-gomod github.com/stamblerre/gocode \
|
||||
#
|
||||
# install Go tools
|
||||
&& mv /tmp/gotools/bin/* /usr/local/bin/ \
|
||||
&& mv gocode-gomod /usr/local/bin/ \
|
||||
#
|
||||
# install golangci-lint
|
||||
&& curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b /usr/local/bin 2>&1 \
|
||||
#
|
||||
# setup paths
|
||||
&& mkdir -p "$GOPATH/src" "$GOPATH/bin" "$GOPATH/pkg/mod" \
|
||||
&& chmod -R 777 "$GOPATH"
|
||||
|
||||
#
|
||||
# turn on go modules
|
||||
ENV GO111MODULE=on
|
||||
|
||||
#
|
||||
# install docker
|
||||
RUN set -eux; \
|
||||
curl -fsSL https://download.docker.com/linux/$(lsb_release -is | tr '[:upper:]' '[:lower:]')/gpg | (OUT=$(apt-key add - 2>&1) || echo $OUT); \
|
||||
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/$(lsb_release -is | tr '[:upper:]' '[:lower:]') $(lsb_release -cs) stable"; \
|
||||
apt-get update; apt-get install -y docker-ce-cli;
|
@ -16,7 +16,7 @@ RUN set -eux; apt-get update; \
|
||||
|
||||
#
|
||||
# copy configuation files
|
||||
COPY supervisord.conf /etc/neko/supervisord/firefox.conf
|
||||
COPY neko.js /usr/lib/firefox-esr/mozilla.cfg
|
||||
COPY autoconfig.js /usr/lib/firefox-esr/defaults/pref/autoconfig.js
|
||||
COPY policies.json /usr/lib/firefox-esr/distribution/policies.json
|
||||
COPY .docker/files/firefox/supervisord.conf /etc/neko/supervisord/firefox.conf
|
||||
COPY .docker/files/firefox/neko.js /usr/lib/firefox-esr/mozilla.cfg
|
||||
COPY .docker/files/firefox/autoconfig.js /usr/lib/firefox-esr/defaults/pref/autoconfig.js
|
||||
COPY .docker/files/firefox/policies.json /usr/lib/firefox-esr/distribution/policies.json
|
||||
|
0
.examples/README.md
Normal file
0
.examples/README.md
Normal file
0
.examples/local/README.md
Normal file
0
.examples/local/README.md
Normal file
16
.examples/local/docker-compose.yaml
Normal file
16
.examples/local/docker-compose.yaml
Normal file
@ -0,0 +1,16 @@
|
||||
version: "2.0"
|
||||
services:
|
||||
neko:
|
||||
image: nurdism/neko:firefox
|
||||
restart: always
|
||||
shm_size: "1gb"
|
||||
ports:
|
||||
- "80:8080"
|
||||
- "59000-59100:59000-59100/udp"
|
||||
environment:
|
||||
DISPLAY: :99.0
|
||||
NEKO_PASSWORD: neko
|
||||
NEKO_PASSWORD_ADMIN: admin
|
||||
NEKO_BIND: :8080
|
||||
NEKO_EPR: 59000-59100
|
||||
NEKO_NAT1TO1: 192.168.0.X
|
0
.examples/simple/README.md
Normal file
0
.examples/simple/README.md
Normal file
32
.github/workflows/build.yml
vendored
Normal file
32
.github/workflows/build.yml
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
name: build
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
paths:
|
||||
- 'client/**'
|
||||
- 'server/**'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
container: nurdism/neko:dev
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Fetch unshallow
|
||||
run: git fetch --prune --tags --unshallow
|
||||
|
||||
- name: Get go dependencies and build server
|
||||
working-directory: server
|
||||
run: |
|
||||
go get -v -t -d .
|
||||
./build
|
||||
|
||||
- name: Get npm dependencies and build Client
|
||||
working-directory: client
|
||||
run: |
|
||||
npm install
|
||||
npm run build
|
44
.github/workflows/deploy.yml
vendored
Normal file
44
.github/workflows/deploy.yml
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
name: deploy
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
paths:
|
||||
- 'client/**'
|
||||
- 'server/**'
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
name: Deploy
|
||||
runs-on: ubuntu-latest
|
||||
container: nurdism/neko:dev
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Fetch unshallow
|
||||
run: git fetch --prune --tags --unshallow
|
||||
|
||||
- name: Get go dependencies and build server
|
||||
working-directory: server
|
||||
run: |
|
||||
go get -v -t -d .
|
||||
./build
|
||||
|
||||
- name: Get npm dependencies and build Client
|
||||
working-directory: client
|
||||
run: |
|
||||
npm install
|
||||
npm run build
|
||||
|
||||
- name: Build the base image
|
||||
run: docker build -f ./.docker/files/base/Dockerfile -t nurdism/neko:base .
|
||||
|
||||
- name: Build the latest image
|
||||
run: docker build -f ./.docker/files/firefox/Dockerfile -t nurdism/neko:latest .
|
||||
|
||||
- name: Push the Docker images
|
||||
run: |
|
||||
echo "${{ secrets.DOCKER_PASSWORD }}" | docker login ${{ secrets.DOCKER_REGISTRY_URL }} -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
|
||||
docker push nurdism/neko:base
|
||||
docker push nurdism/neko:latest
|
@ -6,6 +6,7 @@
|
||||
<img src="https://img.shields.io/docker/pulls/nurdism/neko" alt="pulls">
|
||||
<img src="https://img.shields.io/github/issues/nurdism/neko" alt="issues">
|
||||
<a href="https://discord.gg/3U6hWpC" ><img src="https://discordapp.com/api/guilds/665851821906067466/widget.png" alt="Chat on discord"><a/>
|
||||
<a href="https://github.com/nurdism/neko/actions" ><img src="https://github.com/nurdism/neko/workflows/deploy/badge.svg" alt="build"><a/>
|
||||
</p>
|
||||
<br/>
|
||||
<br/>
|
||||
|
@ -36,7 +36,7 @@
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<template v-if="admin">
|
||||
<template v-if="admin && !child.data.member.admin">
|
||||
<li class="seperator" />
|
||||
<li>
|
||||
<span @click="kick(child.data.member)" style="color: #f04747;">{{ $t('context.kick') }}</span>
|
||||
@ -165,12 +165,12 @@
|
||||
|
||||
kick(member: Member) {
|
||||
this.$swal({
|
||||
title: this.$t('context.confirm.kick_title', { name: member.displayname }),
|
||||
text: this.$t('context.confirm.kick_text', { name: member.displayname }),
|
||||
title: this.$t('context.confirm.kick_title', { name: member.displayname }) as string,
|
||||
text: this.$t('context.confirm.kick_text', { name: member.displayname }) as string,
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: this.$t('context.confirm.button_yes'),
|
||||
cancelButtonText: this.$t('context.confirm.button_cancel'),
|
||||
confirmButtonText: this.$t('context.confirm.button_yes') as string,
|
||||
cancelButtonText: this.$t('context.confirm.button_cancel') as string,
|
||||
}).then(({ value }) => {
|
||||
if (value) {
|
||||
this.$accessor.user.kick(member)
|
||||
@ -180,12 +180,12 @@
|
||||
|
||||
ban(member: Member) {
|
||||
this.$swal({
|
||||
title: this.$t('context.confirm.ban_title', { name: member.displayname }),
|
||||
text: this.$t('context.confirm.ban_text', { name: member.displayname }),
|
||||
title: this.$t('context.confirm.ban_title', { name: member.displayname }) as string,
|
||||
text: this.$t('context.confirm.ban_text', { name: member.displayname }) as string,
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: this.$t('context.confirm.button_yes'),
|
||||
cancelButtonText: this.$t('context.confirm.button_cancel'),
|
||||
confirmButtonText: this.$t('context.confirm.button_yes') as string,
|
||||
cancelButtonText: this.$t('context.confirm.button_cancel') as string,
|
||||
}).then(({ value }) => {
|
||||
if (value) {
|
||||
this.$accessor.user.ban(member)
|
||||
@ -195,12 +195,12 @@
|
||||
|
||||
mute(member: Member) {
|
||||
this.$swal({
|
||||
title: this.$t('context.confirm.mute_title', { name: member.displayname }),
|
||||
text: this.$t('context.confirm.mute_text', { name: member.displayname }),
|
||||
title: this.$t('context.confirm.mute_title', { name: member.displayname }) as string,
|
||||
text: this.$t('context.confirm.mute_text', { name: member.displayname }) as string,
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: this.$t('context.confirm.button_yes'),
|
||||
cancelButtonText: this.$t('context.confirm.button_cancel'),
|
||||
confirmButtonText: this.$t('context.confirm.button_yes') as string,
|
||||
cancelButtonText: this.$t('context.confirm.button_cancel') as string,
|
||||
}).then(({ value }) => {
|
||||
if (value) {
|
||||
this.$accessor.user.mute(member)
|
||||
@ -210,12 +210,12 @@
|
||||
|
||||
unmute(member: Member) {
|
||||
this.$swal({
|
||||
title: this.$t('context.confirm.unmute_title', { name: member.displayname }),
|
||||
text: this.$t('context.confirm.unmute_text', { name: member.displayname }),
|
||||
title: this.$t('context.confirm.unmute_title', { name: member.displayname }) as string,
|
||||
text: this.$t('context.confirm.unmute_text', { name: member.displayname }) as string,
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: this.$t('context.confirm.button_yes'),
|
||||
cancelButtonText: this.$t('context.confirm.button_cancel'),
|
||||
confirmButtonText: this.$t('context.confirm.button_yes') as string,
|
||||
cancelButtonText: this.$t('context.confirm.button_cancel') as string,
|
||||
}).then(({ value }) => {
|
||||
if (value) {
|
||||
this.$accessor.user.unmute(member)
|
||||
|
@ -4,11 +4,11 @@
|
||||
<ul>
|
||||
<li :class="{ active: tab === 'chat' }" @click.stop.prevent="change('chat')">
|
||||
<i class="fas fa-comment-alt" />
|
||||
<span>{{ $t('chat') }}</span>
|
||||
<span>{{ $t('side.chat') }}</span>
|
||||
</li>
|
||||
<li :class="{ active: tab === 'settings' }" @click.stop.prevent="change('settings')">
|
||||
<i class="fas fa-sliders-h" />
|
||||
<span>{{ $t('settings') }}</span>
|
||||
<span>{{ $t('side.settings') }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -161,6 +161,7 @@
|
||||
private observer = new ResizeObserver(this.onResise.bind(this))
|
||||
private focused = false
|
||||
private fullscreen = false
|
||||
private activeKeys: Set<number> = new Set()
|
||||
|
||||
get admin() {
|
||||
return this.$accessor.user.admin
|
||||
@ -333,12 +334,14 @@
|
||||
})
|
||||
|
||||
document.addEventListener('focusin', this.onFocus.bind(this))
|
||||
document.addEventListener('focusout', this.onBlur.bind(this))
|
||||
}
|
||||
|
||||
beforeDestroy() {
|
||||
this.observer.disconnect()
|
||||
this.$accessor.video.setPlayable(false)
|
||||
document.removeEventListener('focusin', this.onFocus.bind(this))
|
||||
document.removeEventListener('focusout', this.onBlur.bind(this))
|
||||
}
|
||||
|
||||
play() {
|
||||
@ -401,6 +404,17 @@
|
||||
}
|
||||
}
|
||||
|
||||
onBlur() {
|
||||
if (!this.focused || !this.hosting || this.locked) {
|
||||
return
|
||||
}
|
||||
|
||||
for (let key of this.activeKeys) {
|
||||
this.$client.sendData('keyup', { key })
|
||||
this.activeKeys.delete(key)
|
||||
}
|
||||
}
|
||||
|
||||
onMousePos(e: MouseEvent) {
|
||||
const { w, h } = this.$accessor.video.resolution
|
||||
const rect = this._overlay.getBoundingClientRect()
|
||||
@ -466,15 +480,15 @@
|
||||
// frick you firefox
|
||||
getCode(e: KeyboardEvent): number {
|
||||
let key = e.keyCode
|
||||
if (key === 59 && e.key === ';') {
|
||||
if (key === 59 && (e.key === ';' || e.key === ':')) {
|
||||
key = 186
|
||||
}
|
||||
|
||||
if (key === 61 && e.key === '=') {
|
||||
if (key === 61 && (e.key === '=' || e.key === '+')) {
|
||||
key = 187
|
||||
}
|
||||
|
||||
if (key === 173 && e.key === '-') {
|
||||
if (key === 173 && (e.key === '-' || e.key === '_')) {
|
||||
key = 189
|
||||
}
|
||||
|
||||
@ -486,7 +500,9 @@
|
||||
return
|
||||
}
|
||||
|
||||
this.$client.sendData('keydown', { key: this.getCode(e) })
|
||||
let key = this.getCode(e)
|
||||
this.$client.sendData('keydown', { key })
|
||||
this.activeKeys.add(key)
|
||||
}
|
||||
|
||||
onKeyUp(e: KeyboardEvent) {
|
||||
@ -494,7 +510,9 @@
|
||||
return
|
||||
}
|
||||
|
||||
this.$client.sendData('keyup', { key: this.getCode(e) })
|
||||
let key = this.getCode(e)
|
||||
this.$client.sendData('keyup', { key })
|
||||
this.activeKeys.delete(key)
|
||||
}
|
||||
|
||||
onResise() {
|
||||
|
@ -1,13 +1,13 @@
|
||||
export const chat = 'Chat'
|
||||
export const settings = 'Settings'
|
||||
export const logout = 'logout'
|
||||
export const unsupported = 'this browser does not support webrtc'
|
||||
export const admin_loggedin = 'You are logged in as an admin'
|
||||
export const you = 'You'
|
||||
export const ok = 'ok'
|
||||
export const send_a_message = 'Send a message'
|
||||
export const connected = 'connected'
|
||||
export const disconnected = 'disconnected'
|
||||
|
||||
export const side = {
|
||||
chat: 'Chat',
|
||||
settings: 'Settings',
|
||||
}
|
||||
|
||||
export const connect = {
|
||||
title: 'Please Login',
|
||||
@ -37,7 +37,7 @@ export const context = {
|
||||
unmute_text: 'Are you sure you want to unmute {name}?',
|
||||
button_yes: 'Yes',
|
||||
button_cancel: 'Cancel',
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
export const controls = {
|
||||
@ -63,11 +63,15 @@ export const setting = {
|
||||
}
|
||||
|
||||
export const connection = {
|
||||
success: 'Successfully connected',
|
||||
logged_out: 'You have been logged out!',
|
||||
connected: 'Successfully connected',
|
||||
disconnected: 'You have been disconnected',
|
||||
button_confirm: 'Ok',
|
||||
}
|
||||
|
||||
export const notifications = {
|
||||
logged_out: '{name} logged out!',
|
||||
connected: '{name} connected',
|
||||
disconnected: '{name} disconnected',
|
||||
controls_taken: '{name} took the controls',
|
||||
controls_taken_force: 'force took the controls',
|
||||
controls_taken_steal: 'took the controls from {name}',
|
||||
|
@ -54,9 +54,9 @@ export class NekoClient extends BaseClient implements EventEmitter<NekoEvents> {
|
||||
this.disconnect()
|
||||
this.cleanup()
|
||||
this.$vue.$swal({
|
||||
title: this.$vue.$t('notifications.logged_out', { name: this.$vue.$t('you') }),
|
||||
title: this.$vue.$t('connection.logged_out'),
|
||||
icon: 'info',
|
||||
confirmButtonText: this.$vue.$t('ok') as string,
|
||||
confirmButtonText: this.$vue.$t('connection.button_confirm') as string,
|
||||
})
|
||||
}
|
||||
|
||||
@ -75,7 +75,7 @@ export class NekoClient extends BaseClient implements EventEmitter<NekoEvents> {
|
||||
this.$vue.$notify({
|
||||
group: 'neko',
|
||||
type: 'success',
|
||||
title: this.$vue.$t('connection.success') as string,
|
||||
title: this.$vue.$t('connection.connected') as string,
|
||||
duration: 5000,
|
||||
speed: 1000,
|
||||
})
|
||||
@ -86,7 +86,7 @@ export class NekoClient extends BaseClient implements EventEmitter<NekoEvents> {
|
||||
this.$vue.$notify({
|
||||
group: 'neko',
|
||||
type: 'error',
|
||||
title: this.$vue.$t('disconnected') as string,
|
||||
title: this.$vue.$t('connection.disconnected') as string,
|
||||
text: reason ? reason.message : undefined,
|
||||
duration: 5000,
|
||||
speed: 1000,
|
||||
@ -111,10 +111,10 @@ export class NekoClient extends BaseClient implements EventEmitter<NekoEvents> {
|
||||
protected [EVENT.SYSTEM.DISCONNECT]({ message }: DisconnectPayload) {
|
||||
this.onDisconnected(new Error(message))
|
||||
this.$vue.$swal({
|
||||
title: this.$vue.$t('disconnected'),
|
||||
title: this.$vue.$t('connection.disconnected'),
|
||||
text: message,
|
||||
icon: 'error',
|
||||
confirmButtonText: this.$vue.$t('ok') as string,
|
||||
confirmButtonText: this.$vue.$t('connection.button_confirm') as string,
|
||||
})
|
||||
}
|
||||
|
||||
@ -125,7 +125,7 @@ export class NekoClient extends BaseClient implements EventEmitter<NekoEvents> {
|
||||
this.$accessor.user.setMembers(members)
|
||||
this.$accessor.chat.newMessage({
|
||||
id: this.id,
|
||||
content: this.$vue.$t('connected') as string,
|
||||
content: this.$vue.$t('notifications.connected', { name: '' }) as string,
|
||||
type: 'event',
|
||||
created: new Date(),
|
||||
})
|
||||
@ -137,7 +137,7 @@ export class NekoClient extends BaseClient implements EventEmitter<NekoEvents> {
|
||||
if (member.id !== this.id) {
|
||||
this.$accessor.chat.newMessage({
|
||||
id: member.id,
|
||||
content: this.$vue.$t('connected') as string,
|
||||
content: this.$vue.$t('notifications.connected', { name: '' }) as string,
|
||||
type: 'event',
|
||||
created: new Date(),
|
||||
})
|
||||
@ -152,7 +152,7 @@ export class NekoClient extends BaseClient implements EventEmitter<NekoEvents> {
|
||||
|
||||
this.$accessor.chat.newMessage({
|
||||
id: member.id,
|
||||
content: this.$vue.$t('disconnected') as string,
|
||||
content: this.$vue.$t('notifications.disconnected', { name: '' }) as string,
|
||||
type: 'event',
|
||||
created: new Date(),
|
||||
})
|
||||
|
@ -25,7 +25,7 @@
|
||||
```shell
|
||||
sudo ufw allow 80/tcp # if you have ufw installed/enabled
|
||||
sudo ufw allow 59000:59100/udp
|
||||
wget https://raw.githubusercontent.com/nurdism/neko/master/docker-compose.yaml
|
||||
wget https://raw.githubusercontent.com/nurdism/neko/master/.examples/simple/docker-compose.yaml
|
||||
sudo docker-compose up -d
|
||||
```
|
||||
5. Visit the IP address server in your browser and login, the default password is `neko`
|
||||
|
@ -1,5 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
|
||||
BUILD_TIME=`date -u +'%Y-%m-%dT%H:%M:%SZ'`
|
||||
GIT_COMMIT=`git rev-parse --short HEAD`
|
||||
GIT_BRANCH=`git rev-parse --symbolic-full-name --abbrev-ref HEAD`
|
||||
|
@ -2,6 +2,7 @@ package broadcast
|
||||
|
||||
import (
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
"n.eko.moe/neko/internal/gst"
|
||||
"n.eko.moe/neko/internal/types/config"
|
||||
)
|
||||
@ -14,8 +15,8 @@ type BroadcastManager struct {
|
||||
|
||||
func New(config *config.Broadcast) *BroadcastManager {
|
||||
return &BroadcastManager{
|
||||
logger: log.With().Str("module", "remote").Logger(),
|
||||
config: config
|
||||
logger: log.With().Str("module", "remote").Logger(),
|
||||
config: config,
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,13 +29,15 @@ func (manager *BroadcastManager) Start() {
|
||||
)
|
||||
if err != nil {
|
||||
manager.logger.Panic().Err(err).Msg("unable to create rtmp pipeline")
|
||||
}
|
||||
}
|
||||
|
||||
manager.pipeline.Start()
|
||||
manager.pipeline.Start()
|
||||
}
|
||||
|
||||
func (manager *BroadcastManager) Shutdown() error {
|
||||
if (manager.pipeline != nil) {
|
||||
manager.pipeline.Stop()
|
||||
}
|
||||
if manager.pipeline != nil {
|
||||
manager.pipeline.Stop()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ func init() {
|
||||
func CreateRTMPPipeline(pipelineDevice string, pipelineDisplay string, pipelineRTMP string) (*Pipeline, error) {
|
||||
video := fmt.Sprintf(videoSrc, pipelineDisplay)
|
||||
audio := fmt.Sprintf(audioSrc, pipelineDevice)
|
||||
return CreatePipeline(fmt.Sprintf("%s ! x264enc ! flv. ! %s ! faac ! flv. ! flvmux name='flv' ! rtmpsink location='%s'", video, audio, pipelineRTMP))
|
||||
return CreatePipeline(fmt.Sprintf("%s ! x264enc ! flv. ! %s ! faac ! flv. ! flvmux name='flv' ! rtmpsink location='%s'", video, audio, pipelineRTMP), "", 0)
|
||||
}
|
||||
|
||||
// CreateAppPipeline creates a GStreamer Pipeline
|
||||
@ -199,11 +199,11 @@ func CreateAppPipeline(codecName string, pipelineDevice string, pipelineSrc stri
|
||||
return nil, fmt.Errorf("unknown codec %s", codecName)
|
||||
}
|
||||
|
||||
return CreatePipeline(pipelineStr)
|
||||
return CreatePipeline(pipelineStr, codecName, clockRate)
|
||||
}
|
||||
|
||||
// CreatePipeline creates a GStreamer Pipeline
|
||||
func CreatePipeline(pipelineStr string) (*Pipeline, error) {
|
||||
func CreatePipeline(pipelineStr string, codecName string, clockRate float32) (*Pipeline, error) {
|
||||
pipelineStrUnsafe := C.CString(pipelineStr)
|
||||
defer C.free(unsafe.Pointer(pipelineStrUnsafe))
|
||||
|
||||
|
@ -88,6 +88,21 @@ func (manager *SessionManager) Get(id string) (types.Session, bool) {
|
||||
return session, ok
|
||||
}
|
||||
|
||||
func (manager *SessionManager) Admins() []*types.Member {
|
||||
members := []*types.Member{}
|
||||
for _, session := range manager.members {
|
||||
if !session.connected || !session.admin {
|
||||
continue
|
||||
}
|
||||
|
||||
member := session.Member()
|
||||
if member != nil {
|
||||
members = append(members, member)
|
||||
}
|
||||
}
|
||||
return members
|
||||
}
|
||||
|
||||
func (manager *SessionManager) Members() []*types.Member {
|
||||
members := []*types.Member{}
|
||||
for _, session := range manager.members {
|
||||
@ -113,7 +128,7 @@ func (manager *SessionManager) Destroy(id string) error {
|
||||
manager.remote.StopStream()
|
||||
}
|
||||
|
||||
manager.emmiter.Emit("destroyed", id)
|
||||
manager.emmiter.Emit("destroyed", id, session)
|
||||
return err
|
||||
}
|
||||
|
||||
@ -155,9 +170,9 @@ func (manager *SessionManager) OnHostCleared(listener func(id string)) {
|
||||
})
|
||||
}
|
||||
|
||||
func (manager *SessionManager) OnDestroy(listener func(id string)) {
|
||||
func (manager *SessionManager) OnDestroy(listener func(id string, session types.Session)) {
|
||||
manager.emmiter.On("destroyed", func(payload ...interface{}) {
|
||||
listener(payload[0].(string))
|
||||
listener(payload[0].(string), payload[1].(*Session))
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@ import (
|
||||
)
|
||||
|
||||
type Broadcast struct {
|
||||
Enabled string
|
||||
Enabled bool
|
||||
Display string
|
||||
Device string
|
||||
AudioParams string
|
||||
|
@ -124,8 +124,8 @@ func (s *Remote) Set() {
|
||||
|
||||
if len(res) > 0 {
|
||||
width, err1 := strconv.ParseInt(res[1], 10, 64)
|
||||
height, err2 := strconv.ParseInt(res[1], 10, 64)
|
||||
rate, err3 := strconv.ParseInt(res[1], 10, 64)
|
||||
height, err2 := strconv.ParseInt(res[2], 10, 64)
|
||||
rate, err3 := strconv.ParseInt(res[3], 10, 64)
|
||||
|
||||
if err1 == nil && err2 == nil && err3 == nil {
|
||||
s.ScreenWidth = int(width)
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
type WebSocket struct {
|
||||
Password string
|
||||
AdminPassword string
|
||||
Proxy bool
|
||||
}
|
||||
|
||||
func (WebSocket) Init(cmd *cobra.Command) error {
|
||||
@ -21,10 +22,16 @@ func (WebSocket) Init(cmd *cobra.Command) error {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd.PersistentFlags().Bool("proxy", false, "enable reverse proxy mode")
|
||||
if err := viper.BindPFlag("proxy", cmd.PersistentFlags().Lookup("proxy")); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *WebSocket) Set() {
|
||||
s.Password = viper.GetString("password")
|
||||
s.AdminPassword = viper.GetString("password_admin")
|
||||
s.Proxy = viper.GetBool("proxy")
|
||||
}
|
||||
|
@ -36,12 +36,13 @@ type SessionManager interface {
|
||||
Has(id string) bool
|
||||
Get(id string) (Session, bool)
|
||||
Members() []*Member
|
||||
Admins() []*Member
|
||||
Destroy(id string) error
|
||||
Clear() error
|
||||
Broadcast(v interface{}, exclude interface{}) error
|
||||
OnHost(listener func(id string))
|
||||
OnHostCleared(listener func(id string))
|
||||
OnDestroy(listener func(id string))
|
||||
OnDestroy(listener func(id string, session Session))
|
||||
OnCreated(listener func(id string, session Session))
|
||||
OnConnected(listener func(id string, session Session))
|
||||
}
|
||||
|
@ -230,7 +230,7 @@ func (h *MessageHandler) adminKick(id string, session types.Session, payload *me
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := target.Kick("You have been kicked"); err != nil {
|
||||
if err := target.Kick("kicked"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -280,7 +280,7 @@ func (h *MessageHandler) adminBan(id string, session types.Session, payload *mes
|
||||
|
||||
h.banned[address[0]] = true
|
||||
|
||||
if err := target.Kick("You have been banned"); err != nil {
|
||||
if err := target.Kick("banned"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -29,19 +29,26 @@ func (h *MessageHandler) Connected(id string, socket *WebSocket) (bool, string,
|
||||
ok, banned := h.banned[address]
|
||||
if ok && banned {
|
||||
h.logger.Debug().Str("address", address).Msg("banned")
|
||||
return false, "This IP has been banned", nil
|
||||
return false, "banned", nil
|
||||
}
|
||||
}
|
||||
|
||||
if h.locked {
|
||||
h.logger.Debug().Msg("server locked")
|
||||
return false, "Server is currently locked", nil
|
||||
session, ok := h.sessions.Get(id)
|
||||
if !ok || !session.Admin() {
|
||||
h.logger.Debug().Msg("server locked")
|
||||
return false, "locked", nil
|
||||
}
|
||||
}
|
||||
|
||||
return true, "", nil
|
||||
}
|
||||
|
||||
func (h *MessageHandler) Disconnected(id string) error {
|
||||
if h.locked && len(h.sessions.Admins()) == 0 {
|
||||
h.locked = false
|
||||
}
|
||||
|
||||
return h.sessions.Destroy(id)
|
||||
}
|
||||
|
||||
|
@ -70,7 +70,7 @@ func (ws *WebSocketHandler) Start() error {
|
||||
}
|
||||
})
|
||||
|
||||
ws.sessions.OnDestroy(func(id string) {
|
||||
ws.sessions.OnDestroy(func(id string, session types.Session) {
|
||||
if err := ws.handler.SessionDestroyed(id); err != nil {
|
||||
ws.logger.Warn().Str("id", id).Err(err).Msg("session destroyed with and error")
|
||||
} else {
|
||||
@ -131,7 +131,7 @@ func (ws *WebSocketHandler) Upgrade(w http.ResponseWriter, r *http.Request) erro
|
||||
|
||||
if err = connection.WriteJSON(message.Disconnect{
|
||||
Event: event.SYSTEM_DISCONNECT,
|
||||
Message: "invalid password",
|
||||
Message: "invalid_password",
|
||||
}); err != nil {
|
||||
ws.logger.Error().Err(err).Msg("failed to send disconnect")
|
||||
}
|
||||
@ -191,7 +191,11 @@ func (ws *WebSocketHandler) Upgrade(w http.ResponseWriter, r *http.Request) erro
|
||||
}
|
||||
|
||||
func (ws *WebSocketHandler) authenticate(r *http.Request) (string, string, bool, error) {
|
||||
ip := utils.ReadUserIP(r)
|
||||
ip := r.RemoteAddr
|
||||
|
||||
if ws.conf.Proxy {
|
||||
ip = utils.ReadUserIP(r)
|
||||
}
|
||||
|
||||
id, err := utils.NewUID(32)
|
||||
if err != nil {
|
||||
|
Loading…
Reference in New Issue
Block a user