support skynet

This commit is contained in:
2020-02-04 19:37:46 +01:00
parent aea57286d9
commit 3ebf9785da
20 changed files with 852 additions and 611 deletions

16
go.mod
View File

@@ -6,24 +6,10 @@ require (
fornaxian.com/pixeldrain-api v0.0.0-20191216095319-0533f903c681
github.com/Fornaxian/config v0.0.0-20180915150834-ac41cf746a70
github.com/Fornaxian/log v0.0.0-20190617093801-1c7ce9a7c9b3
github.com/Fornaxian/pd_mime_type v0.0.0-20200204165508-2815edf3a145
github.com/google/uuid v1.1.1
github.com/gopherjs/gopherjs v0.0.0-20191106031601-ce3c9ade29de // indirect
github.com/julienschmidt/httprouter v1.3.0
github.com/k0kubun/pp v3.0.1+incompatible // indirect
github.com/kisielk/gotool v1.0.0 // indirect
github.com/mattn/go-colorable v0.1.4 // indirect
github.com/mattn/go-isatty v0.0.11 // indirect
github.com/microcosm-cc/bluemonday v1.0.2
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86 // indirect
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab // indirect
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca // indirect
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 // indirect
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
github.com/spf13/cobra v0.0.5 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/timakin/gonvert v0.0.0-20170112000238-5dce59dbd0d8
golang.org/x/crypto v0.0.0-20200109152110-61a87790db17 // indirect
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1 // indirect
golang.org/x/tools v0.0.0-20200114052453-d31a08c2edf2 // indirect
gopkg.in/russross/blackfriday.v2 v2.0.0
)

32
go.sum
View File

@@ -10,6 +10,10 @@ github.com/Fornaxian/config v0.0.0-20180915150834-ac41cf746a70 h1:yRkXab8h+BAWEp
github.com/Fornaxian/config v0.0.0-20180915150834-ac41cf746a70/go.mod h1:Ig5am30IOP/eqsjogI1TuSlOTIeTPHoMOpYYM1bisww=
github.com/Fornaxian/log v0.0.0-20190617093801-1c7ce9a7c9b3 h1:PfKr7anK3z4kLG9V6BbbKOVFhVaGEAJi4HxXCAa+QeU=
github.com/Fornaxian/log v0.0.0-20190617093801-1c7ce9a7c9b3/go.mod h1:jdnyerqAlXJJpQmpyrdmSYMitRaRZ8RejEXuXz6n5QY=
github.com/Fornaxian/pd_mime_type v0.0.0-20200204164318-fc5d8b4479f9 h1:8cg0suW9Ny88xGYnaFyfXG5CH7Vxu8jm8PAwnZM4JOk=
github.com/Fornaxian/pd_mime_type v0.0.0-20200204164318-fc5d8b4479f9/go.mod h1:Ew6h8nlacK6H8aABMDUYN3uaO4Rpw2HLKQZ2ntEybqM=
github.com/Fornaxian/pd_mime_type v0.0.0-20200204165508-2815edf3a145 h1:2a8cFtVwEvK7NeimwAEoSUdf4hC80cXpnj3s4pHga+c=
github.com/Fornaxian/pd_mime_type v0.0.0-20200204165508-2815edf3a145/go.mod h1:Ew6h8nlacK6H8aABMDUYN3uaO4Rpw2HLKQZ2ntEybqM=
github.com/Fornaxian/unifilter v0.0.0-20180623154047-e65e144d5942/go.mod h1:ofV5syadd2nI4gOc/rP1yPnXkARgm+E1D/U38mbUj44=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
@@ -17,6 +21,7 @@ github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dchest/threefish v0.0.0-20120919164726-3ecf4c494abf/go.mod h1:bXVurdTuvOiJu7NHALemFe0JMvC2UmwYHW+7fcZaZ2M=
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
@@ -25,6 +30,7 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gopherjs/gopherjs v0.0.0-20191106031601-ce3c9ade29de h1:F7WD09S8QB4LrkEpka0dFPLSotH11HRpCsLIbIcJ7sU=
@@ -45,6 +51,9 @@ github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/reedsolomon v1.9.2/go.mod h1:CwCi+NUr9pqSVktrkN+Ondf06rkhYZ/pcNv7fu+8Un4=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
@@ -67,9 +76,12 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca h1:NugYot0LIVPxTvN8n+Kvkn6TrbMyxQiuvKdEwFdR9vI=
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 h1:bUGsEnyNbVPw06Bs80sCeARAlK8lhwqGyi6UT8ymuGk=
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
@@ -86,7 +98,9 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/timakin/gonvert v0.0.0-20170112000238-5dce59dbd0d8 h1:gw/M1/pCu7oELGHZ6rvktNmMbdWhf9kHc7WYrbLeKdo=
github.com/timakin/gonvert v0.0.0-20170112000238-5dce59dbd0d8/go.mod h1:oqLl90kSlp4+8wMQKql9ZdQGa4/5pVCxOOpTVWkoyV0=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
@@ -104,6 +118,7 @@ gitlab.com/NebulousLabs/threadgroup v0.0.0-20180716154133-88a11db9e46c/go.mod h1
gitlab.com/NebulousLabs/writeaheadlog v0.0.0-20190703190009-cb822c37bc94/go.mod h1:Lhpa9AcbWcYKcc4amZsOHqJdQglnkWrGuUI68XC7U2Q=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413 h1:ULYEB3JvPRE/IfO+9uO7vKV/xzVTO7XPAwm8xbf4w2g=
@@ -112,13 +127,17 @@ golang.org/x/crypto v0.0.0-20200109152110-61a87790db17 h1:nVJ3guKA9qdkEQ3TUdXI9Q
golang.org/x/crypto v0.0.0-20200109152110-61a87790db17/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20191206065243-da761ea9ff43/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee h1:WG0RUwxtNT4qqaXX3DPA8zHFNm/D9xaBpxzHt1WcA/E=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -135,11 +154,24 @@ golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e h1:FDhOuMEY4JVRztM/gsbk+IKUQ8kj74bxZrgw87eMMVc=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20200114052453-d31a08c2edf2 h1:FAGfnR+fyptW02iTeG8Lytc+6v8yqyQJIx/JMZhMA5M=
golang.org/x/tools v0.0.0-20200114052453-d31a08c2edf2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130224948-02f1738cbe39 h1:5ERHXLQfA0b8cHOwaOfWaaGekrA4+Ka/N74zilLnsIk=
golang.org/x/tools v0.0.0-20200130224948-02f1738cbe39/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74 h1:KW20qMcLRWuIgjdCpHFJbVZA7zsDKtFXPNcm7/eI5ZA=
golang.org/x/tools/gopls v0.3.0 h1:l9KKK1/n6CIbfgaUvHBWAvCfOxcl1N+KSOK79OlPIao=
golang.org/x/tools/gopls v0.3.0/go.mod h1:vvBkm7WBjHNudDeK7Sg7HeR+sKt6yp5TD/4NQaTZzRs=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/russross/blackfriday.v2 v2.0.0 h1:+FlnIV8DSQnT7NZ43hcVKcdJdzZoeCmJj4Ql8gq5keA=
gopkg.in/russross/blackfriday.v2 v2.0.0/go.mod h1:6sSBNz/GtOm/pJTuh5UmBK2ZHfmnxGbl2NZg1UliSOI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
mvdan.cc/xurls/v2 v2.1.0 h1:KaMb5GLhlcSX+e+qhbRJODnUUBvlw01jt4yrjFIHAuA=
mvdan.cc/xurls/v2 v2.1.0/go.mod h1:5GrSd9rOnKOpZaji1OZLYL/yeAAtGDlo/cFe+8K5n8E=

View File

@@ -7,11 +7,12 @@ import (
"net/http"
"net/url"
"strings"
"time"
"github.com/Fornaxian/log"
)
var client = &http.Client{}
var client = &http.Client{Timeout: time.Minute * 5}
// PixelAPI is the Pixeldrain API client
type PixelAPI struct {

View File

@@ -22,6 +22,17 @@ function addUploadHistory(fileID) {
localStorage.setItem("uploaded_files", fileID + "," + uploads);
}
function printDate(date, hours, minutes, seconds) {
let dateStr = date.getFullYear()
+"-"+("00"+(date.getMonth()+1)).slice(-2)
+"-"+("00"+date.getDate()).slice(-2)
if (hours) { dateStr += " "+("00"+date.getHours()).slice(-2) }
if (minutes) { dateStr += ":"+("00"+date.getMinutes()).slice(-2) }
if (seconds) { dateStr += ":"+("00"+date.getMinutes()).slice(-2) }
return dateStr
}
function copyText(text) {
// Create a textarea to copy the text from
let ta = document.createElement("textarea");

View File

@@ -190,12 +190,7 @@ DirectoryElement.prototype.createFileButton = function(file, index) {
let cell = document.createElement("div")
cell.style.width = this.fieldDateWidth
let label = document.createElement("span")
let date = new Date(file.dateCreated)
label.innerText = date.getFullYear()
+"-"+("00"+(date.getMonth()+1)).slice(-2)
+"-"+("00"+date.getDate()).slice(-2)
+" "+("00"+date.getHours()).slice(-2)
+":"+("00"+date.getMinutes()).slice(-2)
label.innerText = printDate(new Date(file.dateCreated), true, true, false)
cell.appendChild(label)
el.appendChild(cell)
}

View File

@@ -1,86 +1,86 @@
function DetailsWindow(viewer) {
this.viewer = viewer;
this.visible = false;
this.fileID = "";
this.graph = 0;
this.viewer = viewer
this.visible = false
this.fileID = ""
this.graph = 0
this.divPopup = document.getElementById("details_popup");
this.btnDetails = document.getElementById("btn_details");
this.btnCloseDetails = document.getElementById("btn_close_details");
this.divFileDetails = document.getElementById("info_file_details");
this.divPopup = document.getElementById("details_popup")
this.btnDetails = document.getElementById("btn_details")
this.btnCloseDetails = document.getElementById("btn_close_details")
this.divFileDetails = document.getElementById("info_file_details")
this.btnDetails.addEventListener("click", () => { this.toggle(); });
this.btnCloseDetails.addEventListener("click", () => { this.toggle(); });
this.btnDetails.addEventListener("click", () => { this.toggle() })
this.btnCloseDetails.addEventListener("click", () => { this.toggle() })
}
DetailsWindow.prototype.toggle = function() {
if (this.visible) {
this.divPopup.style.opacity = "0";
this.divPopup.style.visibility = "hidden";
this.btnDetails.classList.remove("button_highlight");
this.visible = false;
this.divPopup.style.opacity = "0"
this.divPopup.style.visibility = "hidden"
this.btnDetails.classList.remove("button_highlight")
this.visible = false
} else {
this.divPopup.style.opacity = "1";
this.divPopup.style.visibility = "visible";
this.btnDetails.classList.add("button_highlight");
this.visible = true;
this.divPopup.style.opacity = "1"
this.divPopup.style.visibility = "visible"
this.btnDetails.classList.add("button_highlight")
this.visible = true
// This is a workaround for a chrome bug which makes it so hidden
// windows can't be scrolled after they are shown
this.divPopup.focus();
this.divPopup.focus()
if (this.graph === 0) {
this.renderGraph();
this.renderGraph()
}
this.updateGraph(this.fileID);
this.updateGraph(this.fileID)
}
}
DetailsWindow.prototype.setDetails = function(file) {
let desc = "";
let desc = ""
if (this.viewer.isList) {
desc = file.description;
desc = file.description
}
this.fileID = file.id;
this.fileID = file.id
this.divFileDetails.innerHTML = "<table>"
+ "<tr><td>Name<td><td>" + escapeHTML(file.name) + "</td></tr>"
+ "<tr><td>URL<td><td><a href=\"/u/" + file.id + "\">"+domainURL()+"/u/" + file.id + "</a></td></tr>"
+ "<tr><td>URL<td><td><a href=\""+file.link+"\">"+file.link+"</a></td></tr>"
+ "<tr><td>Mime Type<td><td>" + escapeHTML(file.mime_type) + "</td></tr>"
+ "<tr><td>ID<td><td>" + file.id + "</td></tr>"
+ "<tr><td>Size<td><td>" + formatDataVolume(file.size, 4) + "</td></tr>"
+ "<tr><td>Bandwidth<td><td>" + formatDataVolume(file.bandwidth_used, 4) + "</td></tr>"
+ "<tr><td>Upload Date<td><td>" + file.date_upload + "</td></tr>"
+ "<tr><td>Upload Date<td><td>" + printDate(file.date_created, true, true, true) + "</td></tr>"
+ "<tr><td>Description<td><td>" + escapeHTML(desc) + "</td></tr>"
+ "</table>";
+ "</table>"
if(this.visible) {
this.updateGraph(file.id);
if(this.visible && file.timeseries_href !== "") {
this.updateGraph(file)
}
}
DetailsWindow.prototype.updateGraph = function(fileID) {
console.log("updating graph "+fileID);
fetch(apiEndpoint+"/file/" + fileID + "/timeseries?interval=60?days=14").then(resp => {
if (!resp.ok) {return null;}
return resp.json();
DetailsWindow.prototype.updateGraph = function(file) {
console.log("updating graph")
fetch(file.timeseries_href+"?interval=60?days=14").then(resp => {
if (!resp.ok) {return null}
return resp.json()
}).then(resp => {
this.graph.data.labels = resp.labels;
this.graph.data.datasets[0].data = resp.downloads;
this.graph.data.datasets[1].data = resp.views;
this.graph.update();
this.graph.data.labels = resp.labels
this.graph.data.datasets[0].data = resp.downloads
this.graph.data.datasets[1].data = resp.views
this.graph.update()
})
}
DetailsWindow.prototype.renderGraph = function() {
console.log("rendering graph");
Chart.defaults.global.defaultFontColor = "#b3b3b3";
Chart.defaults.global.defaultFontSize = 15;
Chart.defaults.global.defaultFontFamily = "Ubuntu";
Chart.defaults.global.aspectRatio = 2.5;
Chart.defaults.global.elements.point.radius = 0;
Chart.defaults.global.tooltips.mode = "index";
Chart.defaults.global.tooltips.axis = "x";
Chart.defaults.global.tooltips.intersect = false;
console.log("rendering graph")
Chart.defaults.global.defaultFontColor = "#b3b3b3"
Chart.defaults.global.defaultFontSize = 15
Chart.defaults.global.defaultFontFamily = "Ubuntu"
Chart.defaults.global.aspectRatio = 2.5
Chart.defaults.global.elements.point.radius = 0
Chart.defaults.global.tooltips.mode = "index"
Chart.defaults.global.tooltips.axis = "x"
Chart.defaults.global.tooltips.intersect = false
this.graph = new Chart(
document.getElementById('bandwidth_chart'),
{
@@ -148,5 +148,5 @@ DetailsWindow.prototype.renderGraph = function() {
}
}
}
);
)
}

View File

@@ -1,178 +1,178 @@
function ListNavigator(viewer, files) {
this.viewer = viewer;
this.files = files;
this.length = files.length;
this.position = 0;
this.history = [];
this.shuffle = false;
this.viewer = viewer
this.files = files
this.length = files.length
this.position = 0
this.history = []
this.shuffle = false
this.divListNavigator = document.getElementById("list_navigator");
this.divListNavigator = document.getElementById("list_navigator")
this.btnDownloadList = document.getElementById("btn_download_list");
this.btnDownloadList = document.getElementById("btn_download_list")
if (files.id !== "") {
this.btnDownloadList.style.display = "";
this.btnDownloadList.addEventListener("click", () => { this.downloadList(); });
this.btnDownloadList.style.display = ""
this.btnDownloadList.addEventListener("click", () => { this.downloadList() })
}
this.btnShuffle = document.getElementById("btn_shuffle");
this.btnShuffle.style.display = "";
this.btnShuffle.addEventListener("click", () => { this.toggleShuffle(); });
this.btnShuffle = document.getElementById("btn_shuffle")
this.btnShuffle.style.display = ""
this.btnShuffle.addEventListener("click", () => { this.toggleShuffle() })
// Render list contents in list navigator div
files.forEach((item, i) => {
let filename;
let filename
if(item.name !== "null"){
filename = item.name;
filename = item.name
}else{
filename = "Removed File";
filename = "Removed File"
}
let d = document.createElement("div");
d.classList = "file_button list_item";
d.addEventListener("click", () => { this.setItem(i); });
d.innerText = filename;
this.divListNavigator.appendChild(d);
});
let d = document.createElement("div")
d.classList = "file_button list_item"
d.addEventListener("click", () => { this.setItem(i) })
d.innerText = filename
this.divListNavigator.appendChild(d)
})
// Make the navigator visible
this.divListNavigator.style.display = "inline-block";
this.divListNavigator.style.display = "inline-block"
// Skip to the file defined in the link hash
let matches = location.hash.match(new RegExp('item=([^&]*)'));
let hashID = matches ? matches[1] : null;
let matches = location.hash.match(new RegExp('item=([^&]*)'))
let hashID = matches ? matches[1] : null
if(Number.isInteger(parseInt(hashID))){
this.setItem(parseInt(hashID));
this.setItem(parseInt(hashID))
}else{
this.setItem(0);
this.setItem(0)
}
}
ListNavigator.prototype.nextItem = function() {
if(this.shuffle){
this.randItem();
return;
this.randItem()
return
}
if (this.position >= this.length) {
this.position = 0;
this.position = 0
} else {
this.position++;
this.position++
}
this.setItem(this.position);
this.setItem(this.position)
}
ListNavigator.prototype.previousItem = function() {
if(this.position === 0){
this.position = this.length - 1;
this.position = this.length - 1
}else{
this.position--;
this.position--
}
this.setItem(this.position);
this.setItem(this.position)
}
ListNavigator.prototype.randItem = function() {
// Avoid viewing the same file multiple times
let rand;
let rand
do {
rand = Math.round(Math.random() * this.length);
console.log("rand is " + rand);
} while(this.history.indexOf(rand) > -1);
rand = Math.round(Math.random() * this.length)
console.log("rand is " + rand)
} while(this.history.indexOf(rand) > -1)
this.setItem(rand);
this.setItem(rand)
}
ListNavigator.prototype.setItem = function(index) {
if(index >= this.length){
this.position = 0;
this.position = 0
}else{
this.position = index;
this.position = index
}
// Set the URL hash
location.hash = "item=" + this.position;
this.viewer.setFile(this.files[this.position]);
location.hash = "item=" + this.position
this.viewer.setFile(this.files[this.position])
this.addToHistory(index);
this.loadThumbnails(index);
this.addToHistory(index)
this.loadThumbnails(index)
document.querySelectorAll("#list_navigator > .file_button_selected").forEach(el => {
el.classList.remove("file_button_selected");
});
el.classList.remove("file_button_selected")
})
let selectedItem = this.divListNavigator.children[this.position];
selectedItem.classList.add("file_button_selected");
let selectedItem = this.divListNavigator.children[this.position]
selectedItem.classList.add("file_button_selected")
let cst = window.getComputedStyle(selectedItem);
let itemWidth = selectedItem.offsetWidth + parseInt(cst.marginLeft) + parseInt(cst.marginRight);
let cst = window.getComputedStyle(selectedItem)
let itemWidth = selectedItem.offsetWidth + parseInt(cst.marginLeft) + parseInt(cst.marginRight)
let start = this.divListNavigator.scrollLeft;
let end = ((this.position * itemWidth) + (itemWidth / 2)) - (this.divListNavigator.clientWidth / 2);
let steps = 60; // One second
let stepSize = (end - start)/steps;
let start = this.divListNavigator.scrollLeft
let end = ((this.position * itemWidth) + (itemWidth / 2)) - (this.divListNavigator.clientWidth / 2)
let steps = 60 // One second
let stepSize = (end - start)/steps
let animateScroll = (pos, step) => {
this.divListNavigator.scrollLeft = pos;
this.divListNavigator.scrollLeft = pos
if (step < steps) {
requestAnimationFrame(() => {
animateScroll(pos+stepSize, step+1);
});
animateScroll(pos+stepSize, step+1)
})
}
};
animateScroll(start, 0);
}
animateScroll(start, 0)
}
ListNavigator.prototype.downloadList = function() {
document.getElementById("download_frame").src = "/api/list/" + this.viewer.listId + "/zip";
document.getElementById("download_frame").src = "/api/list/" + this.viewer.listId + "/zip"
}
ListNavigator.prototype.addToHistory = function(index) {
if(this.history.length >= (this.length - 6)){
this.history.shift();
this.history.shift()
}
this.history.push(index);
this.history.push(index)
}
ListNavigator.prototype.toggleShuffle = function() {
this.shuffle = !this.shuffle; // :P
this.shuffle = !this.shuffle // :P
if(this.shuffle){
document.querySelector("#btn_shuffle > span").innerHTML = "Shuffle&nbsp;&#x2611;"; // Check icon
this.btnShuffle.classList.add("button_highlight");
document.querySelector("#btn_shuffle > span").innerHTML = "Shuffle&nbsp;&#x2611;" // Check icon
this.btnShuffle.classList.add("button_highlight")
}else{
document.querySelector("#btn_shuffle > span").innerHTML = "Shuffle&nbsp;&#x2610;"; // Empty checkbox
this.btnShuffle.classList.remove("button_highlight");
document.querySelector("#btn_shuffle > span").innerHTML = "Shuffle&nbsp;&#x2610;" // Empty checkbox
this.btnShuffle.classList.remove("button_highlight")
}
}
ListNavigator.prototype.loadThumbnails = function(index) {
let startPos = +index - 50;
let endPos = +index + 50;
let startPos = +index - 50
let endPos = +index + 50
// fyi, the + is to let javascript know it's actually a number instead of a string
if(startPos < 0){
startPos = 0;
startPos = 0
}
if(endPos >= this.length){
endPos = this.length - 1;
endPos = this.length - 1
}
let navigatorItems = document.getElementById("list_navigator").children
for (let i = startPos; i <= endPos; i++){
if (navigatorItems[i].innerHTML.includes("list_item_thumbnail")) {
continue; // Thumbnail already loaded
continue // Thumbnail already loaded
}
let thumb = "/api/file/" + this.files[i].id + "/thumbnail?width=48&height=48";
let name = this.files[i].name;
let thumb = "/api/file/" + this.files[i].id + "/thumbnail?width=48&height=48"
let name = this.files[i].name
let itemHtml = "<img src=\"" + thumb + "\" "
+ "class=\"list_item_thumbnail\" alt=\"" + escapeHTML(name) + "\"/>"
+ escapeHTML(name);
+ escapeHTML(name)
navigatorItems[i].innerHTML = itemHtml;
navigatorItems[i].innerHTML = itemHtml
}
}

View File

@@ -1,41 +1,49 @@
function Toolbar(viewer) {
this.viewer = viewer;
this.visible = false;
this.sharebarVisible = false;
this.viewer = viewer
this.visible = false
this.sharebarVisible = false
this.currentFile = null
this.divToolbar = document.getElementById("toolbar");
this.divFilePreview = document.getElementById("filepreview");
this.downloadFrame = document.getElementById("download_frame");
this.spanViews = document.getElementById("stat_views");
this.spanDownloads = document.getElementById("stat_downloads");
this.spanSize = document.getElementById("stat_size");
this.divToolbar = document.getElementById("toolbar")
this.divFilePreview = document.getElementById("filepreview")
this.downloadFrame = document.getElementById("download_frame")
this.spanViews = document.getElementById("stat_views")
this.spanDownloads = document.getElementById("stat_downloads")
this.spanSize = document.getElementById("stat_size")
this.btnToggleToolbar = document.getElementById("btn_toggle_toolbar");
this.btnDownload = document.getElementById("btn_download");
this.btnCopyLink = document.getElementById("btn_copy");
this.spanCopyLink = document.querySelector("#btn_copy > span");
this.btnShare = document.getElementById("btn_share");
this.divSharebar = document.getElementById("sharebar");
this.btnToggleToolbar = document.getElementById("btn_toggle_toolbar")
this.btnDownload = document.getElementById("btn_download")
this.btnCopyLink = document.getElementById("btn_copy")
this.spanCopyLink = document.querySelector("#btn_copy > span")
this.btnShare = document.getElementById("btn_share")
this.divSharebar = document.getElementById("sharebar")
this.btnToggleToolbar.addEventListener("click", () => { this.toggle(); });
this.btnDownload.addEventListener("click", () => { this.download(); });
this.btnCopyLink.addEventListener("click", () => { this.copyUrl(); });
this.btnShare.addEventListener("click", () => { this.toggleSharebar(); });
this.btnToggleToolbar.addEventListener("click", () => { this.toggle() })
this.btnDownload.addEventListener("click", () => { this.download() })
this.btnCopyLink.addEventListener("click", () => { this.copyUrl() })
this.btnShare.addEventListener("click", () => { this.toggleSharebar() })
}
Toolbar.prototype.setFile = function(file) {
this.currentFile = file
this.spanViews.innerText = file.views
this.spanDownloads.innerText = Math.round((file.bandwidth_used/file.size)*10)/10
this.spanSize.innerText = formatDataVolume(file.size, 3)
}
Toolbar.prototype.toggle = function() {
if (this.visible) {
if (this.sharebarVisible) { this.toggleSharebar(); }
if (this.sharebarVisible) { this.toggleSharebar() }
this.divToolbar.style.left = "-8em";
this.divFilePreview.style.left = "0px";
this.btnToggleToolbar.classList.remove("button_highlight");
this.visible = false;
this.divToolbar.style.left = "-8em"
this.divFilePreview.style.left = "0px"
this.btnToggleToolbar.classList.remove("button_highlight")
this.visible = false
} else {
this.divToolbar.style.left = "0px";
this.divFilePreview.style.left = "8em";
this.btnToggleToolbar.classList.add("button_highlight");
this.visible = true;
this.divToolbar.style.left = "0px"
this.divFilePreview.style.left = "8em"
this.btnToggleToolbar.classList.add("button_highlight")
this.visible = true
}
}
@@ -45,132 +53,124 @@ Toolbar.prototype.toggleSharebar = function() {
title: this.viewer.title,
text: "Download " + this.viewer.title + " here",
url: window.location.href
});
return;
})
return
}
if(this.sharebarVisible){
this.divSharebar.style.left = "-8em";
this.divSharebar.style.left = "-8em"
this.btnShare.classList.remove("button_highlight")
this.sharebarVisible = false;
this.sharebarVisible = false
}else{
this.divSharebar.style.left = "8em";
this.divSharebar.style.left = "8em"
this.btnShare.classList.add("button_highlight")
this.sharebarVisible = true;
this.sharebarVisible = true
}
}
Toolbar.prototype.download = function() {
let triggerDL = (captchaResp = "") => {
if (captchaResp === "") {
this.downloadFrame.src = apiEndpoint+"/file/"+
this.viewer.currentFile+"?download";
this.downloadFrame.src = this.currentFile.download_href
} else {
this.downloadFrame.src = apiEndpoint+"/file/"+
this.viewer.currentFile+"?download&recaptcha_response="+captchaResp;
this.downloadFrame.src = this.currentFile.download_href+"&recaptcha_response="+captchaResp
}
}
if (captchaKey === "none"){
if (captchaKey === "none" || captchaKey === ""){
// If the server doesn't support captcha there's no use in checking
// availability
triggerDL();
return;
triggerDL()
return
}
if (recaptchaResponse !== "") {
// Captcha already filled in. Use the saved captcha responsse to
// download the file
triggerDL(recaptchaResponse);
triggerDL(recaptchaResponse)
// Reset the key
recaptchaResponse = "";
return;
recaptchaResponse = ""
return
}
fetch(apiEndpoint+"/file/"+this.viewer.currentFile+"/availability").then(resp => {
return resp.json();
fetch(this.currentFile.file_availability_href).then(resp => {
return resp.json()
}).then(resp => {
let popupDiv = document.getElementById("captcha_popup");
let popupTitle = document.getElementById("captcha_popup_title");
let popupContent = document.getElementById("captcha_popup_content");
let popupDiv = document.getElementById("captcha_popup")
let popupTitle = document.getElementById("captcha_popup_title")
let popupContent = document.getElementById("captcha_popup_content")
let showCaptcha = () => {
// Load the recaptcha script with a load function
let script = document.createElement("script");
script.src = "https://www.google.com/recaptcha/api.js?onload=loadCaptcha&render=explicit";
document.body.appendChild(script);
let script = document.createElement("script")
script.src = "https://www.google.com/recaptcha/api.js?onload=loadCaptcha&render=explicit"
document.body.appendChild(script)
// Show the popup
popupDiv.style.opacity = "1";
popupDiv.style.visibility = "visible";
popupDiv.style.opacity = "1"
popupDiv.style.visibility = "visible"
}
if (resp.value === "file_rate_limited_captcha_required") {
popupTitle.innerText = "Rate limiting enabled!";
popupTitle.innerText = "Rate limiting enabled!"
popupContent.innerText = "This file is using a suspicious "+
"amount of bandwidth relative to its popularity. To "+
"continue downloading this file you will have to "+
"prove that you're a human first.";
showCaptcha();
"prove that you're a human first."
showCaptcha()
} else if (resp.value === "virus_detected_captcha_required") {
popupTitle.innerText = "Malware warning!";
popupTitle.innerText = "Malware warning!"
popupContent.innerText = "According to our scanning "+
"systems this file may contain a virus of type '"+
resp.extra+"'. You can continue downloading this file at "+
"your own risk, but you will have to prove that you're a "+
"human first.";
showCaptcha();
"human first."
showCaptcha()
} else {
console.warn("resp.value not valid: "+resp.value);
triggerDL();
console.warn("resp.value not valid: "+resp.value)
triggerDL()
}
}).catch(e => {
console.warn("fetch availability failed: "+e);
triggerDL();
});
console.warn("fetch availability failed: "+e)
triggerDL()
})
}
Toolbar.prototype.copyUrl = function() {
if(copyText(window.location.href)) {
console.log('Text copied');
this.spanCopyLink.innerText = "Copied!";
console.log('Text copied')
this.spanCopyLink.innerText = "Copied!"
this.btnCopyLink.classList.add("button_highlight")
} else {
console.log('Copying not supported');
this.spanCopyLink.innerText = "Error!";
alert("Your browser does not support copying text.");
console.log('Copying not supported')
this.spanCopyLink.innerText = "Error!"
alert("Your browser does not support copying text.")
}
// Return to normal
setTimeout(() => {
this.spanCopyLink.innerText = "Copy";
this.spanCopyLink.innerText = "Copy"
this.btnCopyLink.classList.remove("button_highlight")
}, 60000);
}
Toolbar.prototype.setStats = function(file) {
this.spanViews.innerText = file.views
this.spanDownloads.innerText = Math.round((file.bandwidth_used/file.size)*10)/10;
this.spanSize.innerText = formatDataVolume(file.size, 3);
}, 60000)
}
// Called by the google recaptcha script
let recaptchaResponse = "";
let recaptchaResponse = ""
function loadCaptcha(){
grecaptcha.render("captcha_popup_captcha", {
sitekey: captchaKey,
theme: "dark",
callback: token => {
recaptchaResponse = token;
document.getElementById("btn_download").click();
recaptchaResponse = token
document.getElementById("btn_download").click()
// Hide the popup
setTimeout(() => {
let popupDiv = document.getElementById("captcha_popup");
popupDiv.style.opacity = "0";
popupDiv.style.visibility = "hidden";
let popupDiv = document.getElementById("captcha_popup")
popupDiv.style.opacity = "0"
popupDiv.style.visibility = "hidden"
}, 1000)
}
});
})
}

View File

@@ -1,27 +1,26 @@
function Viewer(type, viewToken, data) {
// Set defaults
this.toolbar = null;
this.listNavigator = null;
this.detailsWindow = null;
this.divFilepreview = null;
this.currentFile = "";
this.title = ""; // Contains either the file name or list title
this.listId = "";
this.viewToken = "";
this.isList = false;
this.isFile = false;
this.initialized = false;
this.toolbar = null
this.listNavigator = null
this.detailsWindow = null
this.divFilepreview = null
this.title = "" // Contains either the file name or list title
this.listId = ""
this.viewToken = ""
this.isList = false
this.isFile = false
this.initialized = false
this.viewToken = viewToken;
this.toolbar = new Toolbar(this);
this.detailsWindow = new DetailsWindow(this);
this.viewToken = viewToken
this.toolbar = new Toolbar(this)
this.detailsWindow = new DetailsWindow(this)
this.divFilepreview = document.getElementById("filepreview");
this.divFilepreview = document.getElementById("filepreview")
// On small screens the toolbar takes too much space, so it collapses
// automatically
if (this.divFilepreview.clientWidth > 600 && !this.toolbar.visible) {
this.toolbar.toggle();
this.toolbar.toggle()
}
// The close button only works if the window has an opener. So we hide
@@ -31,106 +30,122 @@ function Viewer(type, viewToken, data) {
}
if (type === "file") {
this.isFile = true;
this.currentFile = data.id;
this.title = data.name;
this.setFile(data);
this.isFile = true
this.title = data.name
this.setFile(fileFromAPIResp(data))
} else if (type === "list") {
this.isList = true;
this.listId = data.id;
this.title = data.title;
this.listNavigator = new ListNavigator(this, data.files);
this.isList = true
this.listId = data.id
this.title = data.title
let files = []
for (let i in data.files) {
files.push(fileFromAPIResp(data.files[i]))
}
this.listNavigator = new ListNavigator(this, files)
} else if (type === "skylink") {
this.isFile = true
this.title = data.name
document.getElementById("btn_details").remove()
document.getElementById("stat_views_label").remove()
document.getElementById("stat_views").remove()
document.getElementById("stat_downloads_label").remove()
document.getElementById("stat_downloads").remove()
let file = fileFromSkyNet(data)
console.log(file)
this.setFile(file)
}
this.renderSponsors();
window.addEventListener("resize", e => { this.renderSponsors(e); });
this.renderSponsors()
window.addEventListener("resize", e => { this.renderSponsors(e) })
// Register keyboard shortcuts
document.addEventListener("keydown", e => { this.keyboardEvent(e); });
document.addEventListener("keydown", e => { this.keyboardEvent(e) })
this.initialized = true;
this.initialized = true
}
Viewer.prototype.setFile = function(file) {
this.currentFile = file.id;
if (this.isList) {
document.getElementById("file_viewer_headerbar_title").style.lineHeight = "1em";
document.getElementById("file_viewer_list_title").innerText = this.title;
document.getElementById("file_viewer_file_title").innerText = file.name;
document.title = this.title + " ~ " + file.name + " ~ pixeldrain";
document.getElementById("file_viewer_headerbar_title").style.lineHeight = "1em"
document.getElementById("file_viewer_list_title").innerText = this.title
document.getElementById("file_viewer_file_title").innerText = file.name
document.title = this.title + " ~ " + file.name + " ~ pixeldrain"
} else {
document.getElementById("file_viewer_file_title").innerText = file.name;
document.title = file.name + " ~ pixeldrain";
document.getElementById("file_viewer_file_title").innerText = file.name
document.title = file.name + " ~ pixeldrain"
}
// Update the file details
this.detailsWindow.setDetails(file);
this.toolbar.setStats(file);
this.detailsWindow.setDetails(file)
this.toolbar.setFile(file)
// Register a new view. We don't care what this returns becasue we can't
// do anything about it anyway
fetch(apiEndpoint+"/file/"+file.id+"/view",
{
if (file.view_href !== "") {
fetch(file.view_href, {
method: "POST",
headers: {"Content-Type": "application/x-www-form-urlencoded"},
body: "token="+this.viewToken
}
);
)
}
// Clear the canvas
this.divFilepreview.innerHTML = "";
this.divFilepreview.innerHTML = ""
let nextItem = () => {
if (this.listNavigator !== null) {
this.listNavigator.nextItem();
this.listNavigator.nextItem()
}
}
};
if (
file.mime_type.startsWith("image")
) {
new ImageViewer(this, file).render(this.divFilepreview);
new ImageViewer(this, file).render(this.divFilepreview)
} else if (
file.mime_type.startsWith("video") ||
file.mime_type === "application/matroska" ||
file.mime_type === "application/x-matroska"
) {
new VideoViewer(this, file, nextItem).render(this.divFilepreview);
new VideoViewer(this, file, nextItem).render(this.divFilepreview)
} else if (
file.mime_type.startsWith("audio") ||
file.mime_type === "application/ogg" ||
file.name.endsWith(".mp3")
) {
new AudioViewer(this, file, nextItem).render(this.divFilepreview);
new AudioViewer(this, file, nextItem).render(this.divFilepreview)
} else if (
file.mime_type === "application/pdf" ||
file.mime_type === "application/x-pdf"
) {
new PDFViewer(this, file).render(this.divFilepreview);
new PDFViewer(this, file).render(this.divFilepreview)
} else if (
file.mime_type.startsWith("text") ||
file.id === "demo"
) {
new TextViewer(this, file).render(this.divFilepreview);
new TextViewer(this, file).render(this.divFilepreview)
} else {
new FileViewer(this, file).render(this.divFilepreview);
new FileViewer(this, file).render(this.divFilepreview)
}
}
Viewer.prototype.renderSponsors = function() {
let scale = 1;
let scaleWidth = 1;
let scaleHeight = 1;
let minWidth = 728;
let minHeight = 800;
let scale = 1
let scaleWidth = 1
let scaleHeight = 1
let minWidth = 728
let minHeight = 800
if (window.innerWidth < minWidth) {
scaleWidth = window.innerWidth/minWidth;
scaleWidth = window.innerWidth/minWidth
}
if (window.innerHeight < minHeight) {
scaleHeight = window.innerHeight/minHeight;
scaleHeight = window.innerHeight/minHeight
}
scale = scaleWidth < scaleHeight ? scaleWidth : scaleHeight;
scale = scaleWidth < scaleHeight ? scaleWidth : scaleHeight
// Because of the scale transformation the automatic margins don't work
// anymore. So we have to maunally calculate the margin. Where we take the
@@ -141,14 +156,14 @@ Viewer.prototype.renderSponsors = function() {
if (offset < 0) {
offset = 0
}
document.querySelector(".sponsors > iframe").style.marginLeft = offset+"px";
document.querySelector(".sponsors > iframe").style.marginLeft = offset+"px"
if (scale == 1) {
document.querySelector(".sponsors > iframe").style.transform = "none";
document.querySelector(".sponsors").style.height = "90px";
document.querySelector(".sponsors > iframe").style.transform = "none"
document.querySelector(".sponsors").style.height = "90px"
} else {
document.querySelector(".sponsors > iframe").style.transform = "scale("+scale+")";
document.querySelector(".sponsors").style.height = (scale*90)+"px";
document.querySelector(".sponsors > iframe").style.transform = "scale("+scale+")"
document.querySelector(".sponsors").style.height = (scale*90)+"px"
}
}
@@ -161,36 +176,36 @@ Viewer.prototype.keyboardEvent = function(evt) {
case 65: // A or left arrow key go to previous file
case 37:
if (this.listNavigator != null) {
this.listNavigator.previousItem();
this.listNavigator.previousItem()
}
break;
break
case 68: // D or right arrow key go to next file
case 39:
if (this.listNavigator != null) {
this.listNavigator.nextItem();
this.listNavigator.nextItem()
}
break;
break
case 83:
if (evt.shiftKey) {
this.listNavigator.downloadList(); // SHIFT + S downloads all files in list
this.listNavigator.downloadList() // SHIFT + S downloads all files in list
} else {
this.toolbar.download(); // S to download the current file
this.toolbar.download() // S to download the current file
}
break;
break
case 82: // R to toggle list shuffle
if (this.listNavigator != null) {
this.listNavigator.toggleShuffle();
this.listNavigator.toggleShuffle()
}
break;
break
case 67: // C to copy to clipboard
this.toolbar.copyUrl();
break;
this.toolbar.copyUrl()
break
case 73: // I to open the details window
this.detailsWindow.toggle();
break;
this.detailsWindow.toggle()
break
case 81: // Q to close the window
window.close();
break;
window.close()
break
}
}
@@ -203,3 +218,39 @@ function escapeHTML(str) {
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;');
}
function fileFromAPIResp(resp) {
let file = {
id: resp.id,
name: resp.name,
mime_type: resp.mime_type,
size: resp.size,
date_created: new Date(resp.date_upload),
date_last_view: new Date(resp.date_last_view),
views: resp.views,
bandwidth_used: resp.bandwidth_used,
description: "",
icon_href: apiEndpoint+"/file/"+resp.id+"/thumbnail",
get_href: apiEndpoint+"/file/"+resp.id,
download_href: apiEndpoint+"/file/"+resp.id+"?download",
availability_href: apiEndpoint+"/file/"+resp.id+"/availability",
view_href: apiEndpoint+"/file/"+resp.id+"/view",
timeseries_href: apiEndpoint+"/file/"+resp.id+"/timeseries",
link: domainURL()+"/u/"+resp.id,
}
if (resp.description !== undefined) {
file.description = resp.description
}
return file
}
function fileFromSkyNet(resp) {
let file = fileFromAPIResp(resp)
file.icon_href = "/res/img/mime/empty.png"
file.get_href = "https://siasky.net/"+resp.id
file.download_href = "https://siasky.net/"+resp.id
file.availability_href = ""
file.view_href = ""
file.timeseries_href = ""
file.link = domainURL()+"/s/"+resp.id
return file
}

View File

@@ -1,33 +1,33 @@
function AudioViewer(viewer, file, next) {
this.viewer = viewer;
this.file = file;
this.next = next;
this.viewer = viewer
this.file = file
this.next = next
this.container = document.createElement("div");
this.container.classList = "image-container";
this.container.appendChild(document.createElement("br"));
this.container = document.createElement("div")
this.container.classList = "image-container"
this.container.appendChild(document.createElement("br"))
this.icon = document.createElement("img");
this.icon.src = "/res/img/mime/audio.png";
this.container.appendChild(this.icon);
this.icon = document.createElement("img")
this.icon.src = "/res/img/mime/audio.png"
this.container.appendChild(this.icon)
this.container.appendChild(document.createElement("br"));
this.container.appendChild(document.createTextNode(file.name));
this.container.appendChild(document.createElement("br"));
this.container.appendChild(document.createElement("br"));
this.container.appendChild(document.createElement("br"))
this.container.appendChild(document.createTextNode(this.file.name))
this.container.appendChild(document.createElement("br"))
this.container.appendChild(document.createElement("br"))
this.element = document.createElement("audio");
this.element.autoplay = "autoplay";
this.element.controls = "controls";
this.element.style.width = "90%";
this.element.addEventListener("ended", () => { this.next(); }, false);
this.element = document.createElement("audio")
this.element.autoplay = "autoplay"
this.element.controls = "controls"
this.element.style.width = "90%"
this.element.addEventListener("ended", () => { this.next() }, false)
this.source = document.createElement("source");
this.source.src = apiEndpoint+"/file/"+this.file.id;
this.element.appendChild(this.source);
this.container.appendChild(this.element);
this.source = document.createElement("source")
this.source.src = this.file.get_href
this.element.appendChild(this.source)
this.container.appendChild(this.element)
}
AudioViewer.prototype.render = function(parent) {
parent.appendChild(this.container);
parent.appendChild(this.container)
}

View File

@@ -1,27 +1,27 @@
function FileViewer(viewer, file, next) {
this.viewer = viewer;
this.file = file;
this.next = next;
this.viewer = viewer
this.file = file
this.next = next
this.container = document.createElement("div");
this.container.classList = "image-container";
this.container.appendChild(document.createElement("br"));
this.container = document.createElement("div")
this.container.classList = "image-container"
this.container.appendChild(document.createElement("br"))
this.icon = document.createElement("img");
this.icon.src = apiEndpoint+"/"+file.thumbnail_href;
this.container.appendChild(this.icon);
this.icon = document.createElement("img")
this.icon.src = this.file.icon_href
this.container.appendChild(this.icon)
this.container.appendChild(document.createElement("br"));
this.container.appendChild(document.createTextNode(file.name));
this.container.appendChild(document.createElement("br"));
this.container.appendChild(document.createTextNode("Type: "+file.mime_type));
this.container.appendChild(document.createElement("br"));
this.container.appendChild(document.createElement("br"));
this.container.appendChild(document.createElement("br"))
this.container.appendChild(document.createTextNode(file.name))
this.container.appendChild(document.createElement("br"))
this.container.appendChild(document.createTextNode("Type: "+file.mime_type))
this.container.appendChild(document.createElement("br"))
this.container.appendChild(document.createElement("br"))
this.container.appendChild(document.createTextNode(
"Press the 'Download' button in the menu to download this file"
));
))
}
FileViewer.prototype.render = function(parent) {
parent.appendChild(this.container);
parent.appendChild(this.container)
}

View File

@@ -1,88 +1,86 @@
function ImageViewer(viewer, file) {
this.viewer = viewer;
this.file = file;
this.zoomed = false;
this.x = 0;
this.y = 0;
this.dragging = false;
this.viewer = viewer
this.file = file
this.zoomed = false
this.x = 0
this.y = 0
this.dragging = false
this.container = document.createElement("dv");
this.container.classList = "image-container";
// this.container.style.lineHeight = "0";
this.container = document.createElement("dv")
this.container.classList = "image-container"
this.element = document.createElement("img");
this.element.classList = "pannable center drop-shadow";
this.element.src = apiEndpoint+"/file/"+this.file.id;
this.element.addEventListener("dblclick", (e) => { return this.doubleclick(e); });
this.element.addEventListener("doubletap", (e) => { return this.doubleclick(e); });
this.element.addEventListener("mousedown", (e) => { return this.mousedown(e); });
document.addEventListener("mousemove", (e) => { return this.mousemove(e); });
document.addEventListener("mouseup", (e) => { return this.mouseup(e); });
this.element = document.createElement("img")
this.element.classList = "pannable center drop-shadow"
this.element.src = this.file.get_href
this.element.addEventListener("dblclick", (e) => { return this.doubleclick(e) })
this.element.addEventListener("doubletap", (e) => { return this.doubleclick(e) })
this.element.addEventListener("mousedown", (e) => { return this.mousedown(e) })
document.addEventListener("mousemove", (e) => { return this.mousemove(e) })
document.addEventListener("mouseup", (e) => { return this.mouseup(e) })
this.container.appendChild(this.element);
this.container.appendChild(this.element)
}
ImageViewer.prototype.render = function(parent) {
parent.appendChild(this.container);
parent.appendChild(this.container)
}
ImageViewer.prototype.doubleclick = function(e) {
if (this.zoomed) {
this.element.style.maxWidth = "100%";
this.element.style.maxHeight = "100%";
this.element.style.top = "50%";
this.element.style.left = "auto";
this.element.style.transform = "translateY(-50%)";
this.container.style.overflow = "hidden";
this.zoomed = false;
this.element.style.maxWidth = "100%"
this.element.style.maxHeight = "100%"
this.element.style.top = "50%"
this.element.style.left = "auto"
this.element.style.transform = "translateY(-50%)"
this.container.style.overflow = "hidden"
this.zoomed = false
} else {
this.element.style.maxWidth = "none";
this.element.style.maxHeight = "none";
this.element.style.top = "0";
this.element.style.left = "";
this.element.style.transform = "none";
this.container.style.overflow = "scroll";
this.zoomed = true;
this.element.style.maxWidth = "none"
this.element.style.maxHeight = "none"
this.element.style.top = "0"
this.element.style.left = ""
this.element.style.transform = "none"
this.container.style.overflow = "scroll"
this.zoomed = true
}
e.preventDefault();
e.stopPropagation();
return false;
e.preventDefault()
e.stopPropagation()
return false
}
ImageViewer.prototype.mousedown = function(e) {
if (!this.dragging && e.which === 1 && this.zoomed) {
this.x = e.pageX;
this.y = e.pageY;
this.dragging = true;
this.x = e.pageX
this.y = e.pageY
this.dragging = true
e.preventDefault();
e.stopPropagation();
return false;
e.preventDefault()
e.stopPropagation()
return false
}
}
ImageViewer.prototype.mousemove = function(e) {
if (this.dragging) {
this.container.scrollLeft = this.container.scrollLeft - (e.pageX - this.x);
this.container.scrollTop = this.container.scrollTop - (e.pageY - this.y);
this.container.scrollLeft = this.container.scrollLeft - (e.pageX - this.x)
this.container.scrollTop = this.container.scrollTop - (e.pageY - this.y)
this.x = e.pageX;
this.y = e.pageY;
this.x = e.pageX
this.y = e.pageY
e.preventDefault();
e.stopPropagation();
return false;
e.preventDefault()
e.stopPropagation()
return false
}
}
ImageViewer.prototype.mouseup = function(e) {
if (this.dragging) {
this.dragging = false;
this.dragging = false
e.preventDefault();
e.stopPropagation();
return false;
e.preventDefault()
e.stopPropagation()
return false
}
}

View File

@@ -1,13 +1,12 @@
function PDFViewer(viewer, file) {
this.viewer = viewer;
this.file = file;
this.viewer = viewer
this.file = file
this.container = document.createElement("iframe");
this.container.classList = "image-container";
this.container.style.border = "none";
this.container.src = "/res/misc/pdf-viewer/web/viewer.html?file="+apiEndpoint+"/file/"+file.id;
this.container = document.createElement("iframe")
this.container.classList = "image-container"
this.container.style.border = "none"
this.container.src = "/res/misc/pdf-viewer/web/viewer.html?file="+this.file.get_href
}
PDFViewer.prototype.render = function(parent) {
parent.appendChild(this.container);
parent.appendChild(this.container)
}

View File

@@ -1,56 +1,58 @@
function TextViewer(viewer, file) {
this.viewer = viewer;
this.file = file;
this.pre = null;
this.prettyprint = null;
this.viewer = viewer
this.file = file
this.pre = null
this.prettyprint = null
this.container = document.createElement("div");
this.container.classList = "text-container";
this.container = document.createElement("div")
this.container.classList = "text-container"
if (file.name.endsWith(".md") || file.name.endsWith(".markdown") || file.id === "demo") {
this.getMarkdown();
if (this.file.name.endsWith(".md") || this.file.name.endsWith(".markdown") || file.mime_type === "text/demo") {
this.getMarkdown()
} else {
this.getText();
this.getText()
}
}
TextViewer.prototype.getText = function() {
this.pre = document.createElement("pre");
this.pre.classList = "pre-container prettyprint linenums";
this.pre.innerText = "Loading...";
this.container.appendChild(this.pre);
this.pre = document.createElement("pre")
this.pre.classList = "pre-container prettyprint linenums"
this.pre.innerText = "Loading..."
this.container.appendChild(this.pre)
if (this.file.size > 1<<20) { // File larger than 1 MiB
this.pre.innerText = "File is too large to view online.\nPlease download and view it locally.";
return;
this.pre.innerText = "File is too large to view online.\nPlease download and view it locally."
return
}
fetch(apiEndpoint+"/file/"+this.file.id).then(resp => {
if (!resp.ok) { return Promise.reject(resp.status); }
return resp.text();
fetch(this.file.get_href).then(resp => {
if (!resp.ok) { return Promise.reject(resp.status) }
return resp.text()
}).then(resp => {
this.pre.innerText = resp;
this.pre.innerText = resp
// Load prettyprint script
this.prettyprint = document.createElement("script");
this.prettyprint.src = "https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js?skin=desert";
this.container.appendChild(this.prettyprint);
this.prettyprint = document.createElement("script")
this.prettyprint.src = "https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js?skin=desert"
this.container.appendChild(this.prettyprint)
}).catch(err => {
this.pre.innerText = "Error loading file: "+err;
});
this.pre.innerText = "Error loading file: "+err
})
}
TextViewer.prototype.getMarkdown = function() {
fetch("/u/"+this.file.id+"/preview").then(resp => {
if (!resp.ok) { return Promise.reject(resp.status); }
return resp.text();
fetch(
domainURL()+window.location.pathname+"/preview"
).then(resp => {
if (!resp.ok) { return Promise.reject(resp.status) }
return resp.text()
}).then(resp => {
this.container.innerHTML = resp;
this.container.innerHTML = resp
}).catch(err => {
this.container.innerText = "Error loading file: "+err;
});
this.container.innerText = "Error loading file: "+err
})
}
TextViewer.prototype.render = function(parent) {
parent.appendChild(this.container);
parent.appendChild(this.container)
}

View File

@@ -1,24 +1,24 @@
function VideoViewer(viewer, file, next) {
this.viewer = viewer;
this.file = file;
this.next = next;
this.viewer = viewer
this.file = file
this.next = next
this.vidContainer = document.createElement("div");
this.vidContainer.classList = "image-container";
this.vidContainer = document.createElement("div")
this.vidContainer.classList = "image-container"
this.vidElement = document.createElement("video");
this.vidElement.autoplay = "autoplay";
this.vidElement.controls = "controls";
this.vidElement.classList = "center drop-shadow";
this.vidElement.addEventListener("ended", () => { this.next(); }, false);
this.vidElement = document.createElement("video")
this.vidElement.autoplay = "autoplay"
this.vidElement.controls = "controls"
this.vidElement.classList = "center drop-shadow"
this.vidElement.addEventListener("ended", () => { this.next() }, false)
this.videoSource = document.createElement("source");
this.videoSource.src = apiEndpoint+"/file/"+this.file.id;
this.videoSource = document.createElement("source")
this.videoSource.src = this.file.get_href
this.vidElement.appendChild(this.videoSource);
this.vidContainer.appendChild(this.vidElement);
this.vidElement.appendChild(this.videoSource)
this.vidContainer.appendChild(this.vidElement)
}
VideoViewer.prototype.render = function(parent) {
parent.appendChild(this.vidContainer);
parent.appendChild(this.vidContainer)
}

View File

@@ -1,78 +1,77 @@
function renderFileButton(apiURL, id, title, subtitle) {
let btn = document.createElement("a");
btn.classList = "file_button";
btn.href = "/u/"+id;
btn.target = "_blank";
let thumbnail = document.createElement("img");
thumbnail.src = apiURL+"/file/"+id+"/thumbnail?width=80&height=80";
thumbnail.alt = title;
let titleSpan = document.createElement("span");
titleSpan.classList = "file_button_title";
titleSpan.innerText = title;
let br = document.createElement("br");
let subtitleSpan = document.createElement("span");
subtitleSpan.classList = "file_button_subtitle";
subtitleSpan.innerText = subtitle;
let btn = document.createElement("a")
btn.classList = "file_button"
btn.href = "/u/"+id
btn.target = "_blank"
let thumbnail = document.createElement("img")
thumbnail.src = apiURL+"/file/"+id+"/thumbnail?width=80&height=80"
thumbnail.alt = title
let titleSpan = document.createElement("span")
titleSpan.classList = "file_button_title"
titleSpan.innerText = title
let br = document.createElement("br")
let subtitleSpan = document.createElement("span")
subtitleSpan.classList = "file_button_subtitle"
subtitleSpan.innerText = subtitle
btn.appendChild(thumbnail);
btn.appendChild(titleSpan);
btn.appendChild(br);
btn.appendChild(subtitleSpan);
return btn;
btn.appendChild(thumbnail)
btn.appendChild(titleSpan)
btn.appendChild(br)
btn.appendChild(subtitleSpan)
return btn
}
function getCookie(name) {
var result = new RegExp('(?:^|; )' + encodeURIComponent(name) + '=([^;]*)').exec(document.cookie);
return result ? result[1] : null;
var result = new RegExp('(?:^|; )' + encodeURIComponent(name) + '=([^;]*)').exec(document.cookie)
return result ? result[1] : null
}
// Get the uploads from localstorage
let uploadsStr = localStorage.getItem("uploaded_files");
if (uploadsStr === null) { uploadsStr = ""; }
let uploadsStr = localStorage.getItem("uploaded_files")
if (uploadsStr === null) { uploadsStr = "" }
let uploads = Array();
let uploads = Array()
if (uploadsStr != "") {
uploadsStr = uploadsStr.slice(0, -1); // Strip the trailing comma
uploads = uploadsStr.split(",");
uploadsStr = uploadsStr.slice(0, -1) // Strip the trailing comma
uploads = uploadsStr.split(",")
}
// Get the uploads from a cookie
uploadsStr = getCookie("pduploads");
if (uploadsStr === null) { uploadsStr = ""; }
uploadsStr = getCookie("pduploads")
if (uploadsStr === null) { uploadsStr = "" }
if (uploadsStr != "") {
uploadsStr = uploadsStr.slice(0, -1); // Strip the trailing dot
uploads.push(uploadsStr.split(".").reverse());
uploadsStr = uploadsStr.slice(0, -1) // Strip the trailing dot
uploads.push(uploadsStr.split(".").reverse())
}
// Render all the items
function getHistoryItem() {
let item = uploads.shift();
if (item === undefined || item === "") { return; }
let item = uploads.shift()
if (item === undefined || item === "") { return }
fetch(
apiEndpoint+"/file/"+item+"/info"
).then(resp => {
if (!resp.ok) {
return Promise.reject();
return Promise.reject()
}
return resp.json();
return resp.json()
}).then(resp => {
let date = new Date(resp.date_upload);
document.getElementById("uploaded_files").appendChild(
renderFileButton(
apiEndpoint,
resp.id,
resp.name,
date.getFullYear()+"-"+("00"+(date.getMonth()+1)).slice(-2)+"-"+("00"+date.getDate()).slice(-2)
printDate(new Date(resp.date_upload), true, true, true),
)
);
getHistoryItem();
)
getHistoryItem()
}).catch(err => {
console.log("Fetch failed: "+err)
getHistoryItem();
getHistoryItem()
})
}
getHistoryItem();
getHistoryItem()

View File

@@ -1,27 +1,27 @@
function UploadProgressBar(uploadManager, queueDiv, file){
this.uploadManager = uploadManager;
this.file = file;
this.name = file.name;
this.uploadManager = uploadManager
this.file = file
this.name = file.name
this.uploadDiv = document.createElement("a");
this.uploadDiv.classList.add("file_button");
this.uploadDiv.style.opacity = "0";
this.uploadDiv.innerText = "Queued\n" + this.file.name;
queueDiv.appendChild(this.uploadDiv);
this.uploadDiv = document.createElement("a")
this.uploadDiv.classList.add("file_button")
this.uploadDiv.style.opacity = "0"
this.uploadDiv.innerText = "Queued\n" + this.file.name
queueDiv.appendChild(this.uploadDiv)
// Start uploading the file
this.uploadManager.addFile(
this.file,
this.name,
(progress) => { this.onProgress(progress); },
(id) => { this.onFinished(id); },
(val, msg) => { this.onFailure(val, msg); }
);
(progress) => { this.onProgress(progress) },
(id) => { this.onFinished(id) },
(val, msg) => { this.onFailure(val, msg) }
)
// Browsers don't render the transition if the opacity is set and
// updated in the same frame. So we have to wait a frame (or more)
// before changing the opacity to make sure the transition triggers
window.setTimeout(() => {this.uploadDiv.style.opacity = "1";}, 100)
window.setTimeout(() => {this.uploadDiv.style.opacity = "1"}, 100)
}
UploadProgressBar.prototype.onProgress = function(progress){
@@ -33,7 +33,7 @@ UploadProgressBar.prototype.onProgress = function(progress){
+'var(--file_background_color) '+ ((progress*100)+1) +'%)'
}
UploadProgressBar.prototype.onFinished = function(id){
console.log("Upload finished: "+this.file.name+" "+id);
console.log("Upload finished: "+this.file.name+" "+id)
this.uploadDiv.style.background = 'var(--file_background_color)'
this.uploadDiv.href = '/u/'+id
@@ -55,7 +55,7 @@ UploadProgressBar.prototype.onFinished = function(id){
}
UploadProgressBar.prototype.onFailure = function(val, msg) {
if (val === "") {
val = "Could not connect to server";
val = "Could not connect to server"
}
this.uploadDiv.innerHTML = "" // Remove uploading progress
@@ -65,21 +65,21 @@ UploadProgressBar.prototype.onFailure = function(val, msg) {
this.uploadDiv.appendChild(document.createTextNode(msg+" ("+val+")"))
this.uploadDiv.appendChild(document.createElement("br"))
this.uploadDiv.appendChild(document.createTextNode(this.file.name))
console.log(msg);
console.log(msg)
}
let uploader = null;
let shareTitle = "";
let shareLink = "";
let uploader = null
let shareTitle = ""
let shareLink = ""
function handleUploads(files) {
if (uploader === null){
uploader = new UploadManager(apiEndpoint, uploadsFinished);
uploader = new UploadManager(apiEndpoint, uploadsFinished)
}
if (files.length === 0) {
return;
return
}
for (let i = 0; i < files.length; i++) {
@@ -87,10 +87,10 @@ function handleUploads(files) {
uploader,
document.getElementById("uploads_queue"),
files.item(i)
);
)
}
hideShareButtons();
hideShareButtons()
}
function uploadsFinished() {
@@ -98,35 +98,35 @@ function uploadsFinished() {
shareTitle = ""
// Get the finished uploads from the uploader
let uploadLog = uploader.finishedUploads();
let uploadLog = uploader.finishedUploads()
if (uploadLog.length === 1) {
shareTitle = "Download "+uploadLog[0].fileName+" here";
shareLink = domainURL()+"/u/"+uploadLog[0].fileID;
shareTitle = "Download "+uploadLog[0].fileName+" here"
shareLink = domainURL()+"/u/"+uploadLog[0].fileID
showShareButtons();
showShareButtons()
} else if (uploadLog.length > 1) {
let title = uploadLog.length + " files";
let title = uploadLog.length + " files"
createList(
title, true,
).then(resp => {
console.log("Automatic list ID "+resp.id);
shareTitle = "View "+title+" here";
shareLink = domainURL()+"/l/"+resp.id;
console.log("Automatic list ID "+resp.id)
shareTitle = "View "+title+" here"
shareLink = domainURL()+"/l/"+resp.id
showShareButtons();
showShareButtons()
}).catch(err => {
alert("Failed to generate link. Please check your internet connection and try again.\nError: "+err);
});
alert("Failed to generate link. Please check your internet connection and try again.\nError: "+err)
})
}
}
function createList(title, anonymous) {
let uploads = uploader.finishedUploads();
let files = Array();
let uploads = uploader.finishedUploads()
let files = Array()
for (let i = 0; i < uploads.length; i++) {
files.push({ "id": uploads[i].fileID });
files.push({ "id": uploads[i].fileID })
}
return fetch(
@@ -142,34 +142,34 @@ function createList(title, anonymous) {
}
).then(resp => {
if (!resp.ok) {
return Promise.reject("HTTP error: "+resp.status);
return Promise.reject("HTTP error: "+resp.status)
}
return resp.json();
return resp.json()
})
}
function hideShareButtons() {
document.getElementById("instruction_3_after").style.display = "none";
document.getElementById("instruction_3_after").style.display = "none"
}
function showShareButtons() {
document.getElementById("instruction_3_after").style.display = "";
document.getElementById("instruction_3_after").style.display = ""
if (window.navigator && window.navigator.share) {
document.getElementById("social_buttons").style.display = "none";
document.getElementById("social_buttons").style.display = "none"
} else {
document.getElementById("navigator_share_button").style.display = "none";
document.getElementById("navigator_share_button").style.display = "none"
}
}
function copyLink() {
if(copyText(shareLink)) {
console.log('Text copied');
document.querySelector("#btn_copy_link>span").textContent = "Copied!";
document.getElementById("btn_copy_link").classList.add("button_highlight");
console.log('Text copied')
document.querySelector("#btn_copy_link>span").textContent = "Copied!"
document.getElementById("btn_copy_link").classList.add("button_highlight")
} else {
console.log('Copying not supported');
alert("Your browser does not support copying text.");
console.log('Copying not supported')
alert("Your browser does not support copying text.")
}
}
@@ -179,33 +179,39 @@ function copyLink() {
// Relay click event to hidden file field
document.getElementById("upload_file_button").onclick = function() {
document.getElementById("file_input_field").click();
document.getElementById("file_input_field").click()
}
document.getElementById("file_input_field").onchange = function(evt){
// Start uploading the files async
window.setTimeout(handleUploads(evt.target.files), 1);
window.setTimeout(handleUploads(evt.target.files), 1)
// This resets the file input field
document.getElementById("file_input_field").nodeValue = "";
document.getElementById("file_input_field").nodeValue = ""
}
document.getElementById("upload_text_button").onclick = function() {
window.location.href = '/t/';
window.location.href = '/t/'
}
/*
* Drag 'n Drop upload handlers
*/
document.ondragover = function(e) { e.preventDefault(); e.stopPropagation(); }
document.ondragenter = function(e) { e.preventDefault(); e.stopPropagation(); }
document.ondragover = function(e) {
e.preventDefault()
e.stopPropagation()
}
document.ondragenter = function(e) {
e.preventDefault()
e.stopPropagation()
}
document.addEventListener('drop', function(e){
if (e.dataTransfer && e.dataTransfer.files.length > 0) {
e.preventDefault()
e.stopPropagation()
// Run async to not freeze the page
window.setTimeout(handleUploads(e.dataTransfer.files), 1);
window.setTimeout(handleUploads(e.dataTransfer.files), 1)
}
})
@@ -218,42 +224,65 @@ document.getElementById("btn_social_share").addEventListener("click", function()
title: "Pixeldrain",
text: shareTitle,
url: shareLink
});
});
})
})
document.getElementById("btn_copy_link").addEventListener("click", function() {
copyLink();
});
copyLink()
})
document.getElementById("btn_open_link").addEventListener("click", function() {
window.open(shareLink, '_blank');
});
window.open(shareLink, '_blank')
})
document.getElementById("btn_social_email").addEventListener("click", function() {
window.open('mailto:please@set.address?subject=File%20on%20pixeldrain&body=' + shareLink);
});
window.open('mailto:please@set.address?subject=File%20on%20pixeldrain&body=' + shareLink)
})
document.getElementById("btn_social_twitter").addEventListener("click", function() {
window.open('https://twitter.com/share?url=' + shareLink);
});
window.open('https://twitter.com/share?url=' + shareLink)
})
document.getElementById("btn_social_facebook").addEventListener("click", function() {
window.open('http://www.facebook.com/sharer.php?u=' + shareLink);
});
window.open('http://www.facebook.com/sharer.php?u=' + shareLink)
})
document.getElementById("btn_social_reddit").addEventListener("click", function() {
window.open('https://www.reddit.com/submit?url=' + shareLink);
});
window.open('https://www.reddit.com/submit?url=' + shareLink)
})
document.getElementById("btc_social_tumblr").addEventListener("click", function() {
window.open('http://www.tumblr.com/share/link?url=' + shareLink);
});
window.open('http://www.tumblr.com/share/link?url=' + shareLink)
})
/*
* Link copy buttons
*/
function renderListButton(apiURL, id, title, subtitle) {
let btn = document.createElement("a")
btn.classList = "file_button"
btn.href = "/l/"+id
btn.target = "_blank"
let thumbnail = document.createElement("img")
thumbnail.src = apiURL+"/list/"+id+"/thumbnail?width=80&height=80"
thumbnail.alt = title
let titleSpan = document.createElement("span")
titleSpan.classList = "file_button_title"
titleSpan.innerText = title
let br = document.createElement("br")
let subtitleSpan = document.createElement("span")
subtitleSpan.classList = "file_button_subtitle"
subtitleSpan.innerText = subtitle
btn.appendChild(thumbnail)
btn.appendChild(titleSpan)
btn.appendChild(br)
btn.appendChild(subtitleSpan)
return btn
}
// Create list button
document.getElementById("btn_create_list").addEventListener("click", function(evt) {
let title = prompt(
"You are creating a list containing " + uploader.finishedUploads().length + " files.\n"
+ "What do you want to call it?", "My New Album"
);
)
if(title === null){
return;
return
}
createList(title, false).then(resp => {
document.getElementById("created_lists").appendChild(
@@ -263,91 +292,91 @@ document.getElementById("btn_create_list").addEventListener("click", function(ev
domainURL()+'/l/'+resp.id,
"List creation finished!",
)
);
window.open('/l/'+resp.id, '_blank');
)
window.open('/l/'+resp.id, '_blank')
}).catch(err => {
let div = document.createElement("div")
div.className = "file_button";
div.className = "file_button"
div.innerHTML = "List creation failed<br/>"
+ "The server responded with:<br/>"
+ err;
document.getElementById("created_lists").append(div);
});
});
+ err
document.getElementById("created_lists").append(div)
})
})
let btnCopyLinks = document.getElementById("btn_copy_links");
let btnCopyLinks = document.getElementById("btn_copy_links")
btnCopyLinks.addEventListener("click", function(){
let text = "";
let uploads = uploader.finishedUploads();
let text = ""
let uploads = uploader.finishedUploads()
// Add the text to the textarea
for (let i = 0; i < uploads.length; i++) {
// Example: https://pixeldrain.com/u/abcd1234: Some_file.png
text += domainURL()+"/u/"+uploads[i].fileID+" "+uploads[i].fileName+"\n";
text += domainURL()+"/u/"+uploads[i].fileID+" "+uploads[i].fileName+"\n"
}
if (shareLink.includes("/l/")) {
text += "\n"+shareLink+" All "+uploads.length+" files\n";
text += "\n"+shareLink+" All "+uploads.length+" files\n"
}
// Copy the selected text
if(copyText(text)){
btnCopyLinks.classList.add("button_highlight");
btnCopyLinks.classList.add("button_highlight")
btnCopyLinks.innerHTML = "Links copied to clipboard!"
}else{
btnCopyLinks.classList.add("button_red");
btnCopyLinks.classList.add("button_red")
btnCopyLinks.innerHTML = "Copying links failed"
}
});
})
let btnCopyBBCode = document.getElementById("btn_copy_bbcode");
let btnCopyBBCode = document.getElementById("btn_copy_bbcode")
btnCopyBBCode.addEventListener("click", function(){
let text = "";
let uploads = uploader.finishedUploads();
let text = ""
let uploads = uploader.finishedUploads()
// Add the text to the textarea
for (let i = 0; i < uploads.length; i++) {
// Example: [url=https://pixeldrain.com/u/abcd1234]Some_file.png[/url]
text += "[url="+domainURL()+"/u/"+uploads[i].fileID+"]"+uploads[i].fileName+"[/url]\n";
text += "[url="+domainURL()+"/u/"+uploads[i].fileID+"]"+uploads[i].fileName+"[/url]\n"
}
if (shareLink.includes("/l/")) {
text += "\n[url="+shareLink+"]All "+uploads.length+" files[/url]\n";
text += "\n[url="+shareLink+"]All "+uploads.length+" files[/url]\n"
}
// Copy the selected text
if(copyText(text)){
btnCopyBBCode.classList.add("button_highlight");
btnCopyBBCode.classList.add("button_highlight")
btnCopyBBCode.innerHTML = "BBCode copied to clipboard!"
}else{
btnCopyBBCode.classList.add("button_red");
btnCopyBBCode.classList.add("button_red")
btnCopyBBCode.innerHTML = "Copying links failed"
}
});
})
let btnCopyMarkdown = document.getElementById("btn_copy_markdown");
let btnCopyMarkdown = document.getElementById("btn_copy_markdown")
btnCopyMarkdown.addEventListener("click", function(){
let text = "";
let uploads = uploader.finishedUploads();
let text = ""
let uploads = uploader.finishedUploads()
// Add the text to the textarea
for (let i = 0; i < uploads.length; i++) {
// Example: * [Some_file.png](https://pixeldrain.com/u/abcd1234)
if (uploads.length > 1) { text += " * "; }
text += "["+uploads[i].fileName+"]("+domainURL()+"/u/"+uploads[i].fileID+")\n";
if (uploads.length > 1) { text += " * " }
text += "["+uploads[i].fileName+"]("+domainURL()+"/u/"+uploads[i].fileID+")\n"
}
if (shareLink.includes("/l/")) {
text += " * [All "+uploads.length+" files]("+shareLink+")\n";
text += " * [All "+uploads.length+" files]("+shareLink+")\n"
}
// Copy the selected text
if(copyText(text)){
btnCopyMarkdown.classList.add("button_highlight");
btnCopyMarkdown.classList.add("button_highlight")
btnCopyMarkdown.innerHTML = "Markdown copied to clipboard!"
}else{
btnCopyMarkdown.classList.add("button_red");
btnCopyMarkdown.classList.add("button_red")
btnCopyMarkdown.innerHTML = "Copying links failed"
}
});
})
/*
@@ -359,13 +388,13 @@ document.addEventListener("keydown", function(event){
}
if (event.keyCode === 67) { // c
// Copy links to clipboard
document.getElementById("btn_copy_link").click();
document.getElementById("btn_copy_link").click()
} else if (event.keyCode === 85) { // u
// Click the upload button
document.getElementById("file_input_field").click();
document.getElementById("file_input_field").click()
} else if (event.keyCode === 84) { // t
// Click the text button
document.getElementById("upload_text_button").click();
document.getElementById("upload_text_button").click()
}
console.log(event.keyCode)
});
})

View File

@@ -95,3 +95,45 @@ func (wc *WebController) adminGlobalsForm(td *TemplateData, r *http.Request) (f
}
return f
}
// func (wc *WebController) adminFileDeleteForm(td *TemplateData, r *http.Request) (f Form) {
// if isAdmin, err := td.PixelAPI.UserIsAdmin(); err != nil {
// td.Title = err.Error()
// return Form{Title: td.Title}
// } else if !isAdmin.IsAdmin {
// td.Title = ";)"
// return Form{Title: td.Title}
// }
// td.Title = "Admin file removal"
// f = Form{
// Name: "admin_file_removal",
// Title: td.Title,
// PreFormHTML: template.HTML("<p>Paste any pixeldrain file links in here to remove them</p>"),
// Fields: []Field{
// {
// Name: "files",
// Label: "Files to delete",
// Type: FieldTypeTextarea,
// },
// },
// BackLink: "/admin",
// SubmitLabel: "Submit",
// }
// if f.ReadInput(r) {
// filesText := f.FieldVal("files")
// // Get all links from the text
// strings.Index(filesText, "/u/")
// if len(f.SubmitMessages) == 0 {
// // Request was a success
// f.SubmitSuccess = true
// f.SubmitMessages = []template.HTML{template.HTML(
// fmt.Sprintf("Success! %d values updated", successfulUpdates),
// )}
// }
// }
// return f
// }

View File

@@ -2,10 +2,14 @@ package webcontroller
import (
"fmt"
"io/ioutil"
"net/http"
"strconv"
"strings"
"time"
pdmimetype "github.com/Fornaxian/pd_mime_type"
"fornaxian.com/pixeldrain-web/pixelapi"
"github.com/Fornaxian/log"
"github.com/julienschmidt/httprouter"
@@ -152,3 +156,90 @@ func (wc *WebController) serveListViewer(w http.ResponseWriter, r *http.Request,
log.Error("Error executing template file_viewer: %s", err)
}
}
// ServeFileViewer controller for GET /s/:id
func (wc *WebController) serveSkynetViewer(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
var err error
templateData := wc.newTemplateData(w, r)
// Get the first few bytes from the file to probe the content type and
// length
rq, err := http.NewRequest("GET", "https://siasky.net/"+p.ByName("id"), nil)
if err != nil {
panic(err)
}
// Range header limits the number of bytes which will be read
rq.Header.Set("Range", "bytes=0-1023")
resp, err := wc.httpClient.Do(rq)
if err != nil {
panic(err)
}
defer resp.Body.Close()
if resp.StatusCode >= 500 {
w.WriteHeader(http.StatusInternalServerError)
wc.templates.Get().ExecuteTemplate(w, "500", templateData)
return
} else if resp.StatusCode >= 400 {
w.WriteHeader(http.StatusNotFound)
wc.templates.Get().ExecuteTemplate(w, "file_not_found", templateData)
return
}
head, err := ioutil.ReadAll(resp.Body)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
wc.templates.Get().ExecuteTemplate(w, "500", templateData)
return
}
var fileType = resp.Header.Get("Content-Type")
if fileType == "application/octet-stream" || fileType == "" {
fileType = pdmimetype.Detect(head)
}
// Now get the size of the file from the content-range header
contentRange := resp.Header.Get("Content-Range")
if contentRange == "" {
w.WriteHeader(http.StatusInternalServerError)
wc.templates.Get().ExecuteTemplate(w, "500", templateData)
return
}
contentRange = strings.TrimPrefix(contentRange, "bytes ")
size, err := strconv.ParseUint(strings.Split(contentRange, "/")[1], 10, 64)
if err != nil {
panic(err)
}
templateData.OGData = ""
templateData.Title = fmt.Sprintf("Skylink ~ pixeldrain")
templateData.Other = viewerData{
Type: "skylink",
APIResponse: pixelapi.FileInfo{
Success: true,
ID: p.ByName("id"),
Name: "skynet_file.dat",
Size: size,
Views: 0,
BandwidthUsed: 0,
DateUpload: time.Now(),
DateLastView: time.Now(),
MimeType: fileType,
MimeImage: "",
ThumbnailHREF: "",
Availability: "",
},
}
var templateName = "file_viewer"
if browserCompat(r.UserAgent()) {
templateName = "file_viewer_compat"
}
err = wc.templates.Get().ExecuteTemplate(w, templateName, templateData)
if err != nil && !strings.Contains(err.Error(), "broken pipe") {
log.Error("Error executing template file_viewer: %s", err)
}
}

View File

@@ -6,6 +6,7 @@ import (
"net/http"
"os"
"strings"
"time"
"github.com/google/uuid"
@@ -30,6 +31,8 @@ type WebController struct {
// page-specific variables
captchaSiteKey string
httpClient *http.Client
}
// New initializes a new WebController by registering all the request handlers
@@ -50,6 +53,7 @@ func New(
apiURLInternal: apiURLInternal,
apiURLExternal: apiURLExternal,
sessionCookieDomain: sessionCookieDomain,
httpClient: &http.Client{Timeout: time.Minute * 10},
}
wc.templates = NewTemplateManager(resourceDir, apiURLExternal, debugMode)
wc.templates.ParseTemplates(false)
@@ -88,6 +92,7 @@ func New(
r.GET(p+"/u/:id" /* */, wc.serveFileViewer)
r.GET(p+"/u/:id/preview" /**/, wc.serveFilePreview)
r.GET(p+"/l/:id" /* */, wc.serveListViewer)
r.GET(p+"/s/:id" /* */, wc.serveSkynetViewer)
r.GET(p+"/t" /* */, wc.serveTemplate("paste", false))
r.GET(p+"/donation" /* */, wc.serveTemplate("donation", false))
r.GET(p+"/widgets" /* */, wc.serveTemplate("widgets", false))