mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2026-01-06 04:33:16 -06:00
more
This commit is contained in:
parent
0f7cfa75f3
commit
526a14a92d
486 changed files with 84353 additions and 23865 deletions
5
go.mod
5
go.mod
|
|
@ -21,14 +21,15 @@ require (
|
|||
github.com/go-errors/errors v1.4.0 // indirect
|
||||
github.com/go-fed/activity v1.0.1-0.20210803212804-d866ba75dd0f
|
||||
github.com/go-fed/httpsig v1.1.0
|
||||
github.com/go-pg/pg/v10 v10.10.3
|
||||
github.com/go-playground/validator/v10 v10.7.0 // indirect
|
||||
github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 // indirect
|
||||
github.com/golang/mock v1.6.0 // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/gorilla/sessions v1.2.1 // indirect
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/h2non/filetype v1.1.1
|
||||
github.com/jackc/pgx/v4 v4.13.0
|
||||
github.com/json-iterator/go v1.1.11 // indirect
|
||||
github.com/leodido/go-urn v1.2.1 // indirect
|
||||
github.com/mattn/go-isatty v0.0.13 // indirect
|
||||
|
|
@ -37,7 +38,6 @@ require (
|
|||
github.com/modern-go/reflect2 v1.0.1 // indirect
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
|
||||
github.com/oklog/ulid v1.3.1
|
||||
github.com/onsi/gomega v1.14.0 // indirect
|
||||
github.com/quasoft/memstore v0.0.0-20191010062613-2bce066d2b0b // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
|
|
@ -48,7 +48,6 @@ require (
|
|||
github.com/tidwall/buntdb v1.2.4 // indirect
|
||||
github.com/uptrace/bun v0.4.3
|
||||
github.com/uptrace/bun/dialect/pgdialect v0.4.3
|
||||
github.com/uptrace/bun/driver/pgdriver v0.4.3
|
||||
github.com/urfave/cli/v2 v2.3.0
|
||||
github.com/wagslane/go-password-validator v0.3.0
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97
|
||||
|
|
|
|||
153
go.sum
153
go.sum
|
|
@ -33,6 +33,8 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9
|
|||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
|
||||
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
|
||||
github.com/ReneKroon/ttlcache v1.7.0 h1:8BkjFfrzVFXyrqnMtezAaJ6AHPSsVV10m6w28N/Fgkk=
|
||||
github.com/ReneKroon/ttlcache v1.7.0/go.mod h1:8BGGzdumrIjWxdRx8zpK6L3oGMWvIXdvB2GD1cfvd+I=
|
||||
github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
|
||||
|
|
@ -54,11 +56,16 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P
|
|||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
|
||||
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
|
||||
github.com/coreos/go-oidc/v3 v3.0.0 h1:/mAA0XMgYJw2Uqm7WKGCsKnjitE/+A0FFbOmiRJm7LQ=
|
||||
github.com/coreos/go-oidc/v3 v3.0.0/go.mod h1:rEJ/idjfUyfkBit1eI1fvyr+64/g9dcKpAm8MJMesvo=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/dave/jennifer v1.3.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
|
|
@ -104,7 +111,6 @@ github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod
|
|||
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
|
||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/gavv/httpexpect v2.0.0+incompatible h1:1X9kcRshkSKEjNJJxX9Y9mQ5BRfbxU5kORdjhlA1yX8=
|
||||
github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc=
|
||||
|
|
@ -131,10 +137,8 @@ github.com/go-fed/httpsig v1.1.0/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7
|
|||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-pg/pg/v10 v10.10.3 h1:WobSfk5I+v7XwD1h9x2B7n4slDzjdBIonJ5PID95Aag=
|
||||
github.com/go-pg/pg/v10 v10.10.3/go.mod h1:EmoJGYErc+stNN/1Jf+o4csXuprjxcRztBnn6cHe38E=
|
||||
github.com/go-pg/zerochecker v0.2.0 h1:pp7f72c3DobMWOb2ErtZsnrPaSvHd2W4o9//8HtF4mU=
|
||||
github.com/go-pg/zerochecker v0.2.0/go.mod h1:NJZ4wKL0NmTtz0GKCoJ8kym6Xn/EQzXRl2OnAe7MmDo=
|
||||
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
|
||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM=
|
||||
|
|
@ -146,13 +150,15 @@ github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+
|
|||
github.com/go-playground/validator/v10 v10.6.1/go.mod h1:xm76BBt941f7yWdGnI2DVPFFg1UK3YY04qifoXU3lOk=
|
||||
github.com/go-playground/validator/v10 v10.7.0 h1:gLi5ajTBBheLNt0ctewgq7eolXoDALQd5/y90Hh9ZgM=
|
||||
github.com/go-playground/validator/v10 v10.7.0/go.mod h1:xm76BBt941f7yWdGnI2DVPFFg1UK3YY04qifoXU3lOk=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-test/deep v1.0.1 h1:UQhStjbkDClarlmv0am7OXXO4/GaPdCGiUiMTvi28sg=
|
||||
github.com/go-test/deep v1.0.1/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
|
||||
github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b h1:khEcpUM4yFcxg4/FHQWkvVRmgijNXRfzkIDHh23ggEo=
|
||||
github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM=
|
||||
github.com/goccy/go-json v0.5.1 h1:R9UYTOUvo7eIY9aeDMZ4L6OVtHaSr1k2No9W6MKjXrA=
|
||||
github.com/goccy/go-json v0.5.1/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
|
||||
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI=
|
||||
github.com/golang/geo v0.0.0-20200319012246-673a6f80352d/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI=
|
||||
github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 h1:gtexQ/VGyN+VVFRXSFiguSNcXmS6rkKT+X7FdIrTtfo=
|
||||
|
|
@ -183,7 +189,6 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W
|
|||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
|
|
@ -239,6 +244,53 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO
|
|||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk=
|
||||
github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA=
|
||||
github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0=
|
||||
github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo=
|
||||
github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
|
||||
github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8=
|
||||
github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
|
||||
github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA=
|
||||
github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE=
|
||||
github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s=
|
||||
github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o=
|
||||
github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY=
|
||||
github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI=
|
||||
github.com/jackc/pgconn v1.10.0 h1:4EYhlDVEMsJ30nNj0mmgwIUXoq7e9sMJrVC2ED6QlCU=
|
||||
github.com/jackc/pgconn v1.10.0/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI=
|
||||
github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE=
|
||||
github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8=
|
||||
github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE=
|
||||
github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c=
|
||||
github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65 h1:DadwsjnMwFjfWc9y5Wi/+Zz7xoE5ALHsRQlOctkOiHc=
|
||||
github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A=
|
||||
github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78=
|
||||
github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA=
|
||||
github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg=
|
||||
github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
|
||||
github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
|
||||
github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgproto3/v2 v2.1.1 h1:7PQ/4gLoqnl87ZxL7xjO0DR5gYuviDCZxQJsUlFW1eI=
|
||||
github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
|
||||
github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg=
|
||||
github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc=
|
||||
github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw=
|
||||
github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM=
|
||||
github.com/jackc/pgtype v1.8.1 h1:9k0IXtdJXHJbyAWQgbWr1lU+MEhPXZz6RIXxfR5oxXs=
|
||||
github.com/jackc/pgtype v1.8.1/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4=
|
||||
github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y=
|
||||
github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM=
|
||||
github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc=
|
||||
github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs=
|
||||
github.com/jackc/pgx/v4 v4.13.0 h1:JCjhT5vmhMAf/YwBHLvrBn4OGdIQBiFG6ym8Zmdx570=
|
||||
github.com/jackc/pgx/v4 v4.13.0/go.mod h1:9P4X524sErlaxj0XSGZk7s+LD0eOyu1ZDUrrpznYDF0=
|
||||
github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
|
|
@ -256,18 +308,30 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o
|
|||
github.com/klauspost/compress v1.10.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.10.10 h1:a/y8CglcM7gLGYmlbP/stPE5sR3hbhFRUjCBfd/0B3I=
|
||||
github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
|
||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
|
||||
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8=
|
||||
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/matryer/try v0.0.0-20161228173917-9ac251b645a2/go.mod h1:0KeJpeMD6o+O4hW7qJOT7vyQPKrWmj26uf5wMc/IiIs=
|
||||
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
|
||||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA=
|
||||
|
|
@ -285,24 +349,17 @@ github.com/moul/http2curl v1.0.0 h1:dRMWoAtb+ePxMlLkrCbAqh4TlPHXvoGUSQ323/9Zahs=
|
|||
github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ=
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0=
|
||||
github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
||||
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
|
||||
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
|
||||
github.com/onsi/gomega v1.14.0 h1:ep6kpPVwmr/nTbklSx2nrLNSIO62DoYAhnPNIMhK8gI=
|
||||
github.com/onsi/gomega v1.14.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
|
|
@ -311,13 +368,22 @@ github.com/quasoft/memstore v0.0.0-20191010062613-2bce066d2b0b h1:aUNXCGgukb4gtY
|
|||
github.com/quasoft/memstore v0.0.0-20191010062613-2bce066d2b0b/go.mod h1:wTPjTepVu7uJBYgZ0SdWHQlIas582j6cn2jgk4DDdlg=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
|
||||
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
|
||||
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
|
||||
github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
|
||||
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||
|
|
@ -326,6 +392,8 @@ github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIK
|
|||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
|
|
@ -382,8 +450,6 @@ github.com/uptrace/bun v0.4.3 h1:x6bjDqwjxwM/9Q1eauhkznuvTrz/rLiCK2p4tT63sAE=
|
|||
github.com/uptrace/bun v0.4.3/go.mod h1:aL6D9vPw8DXaTQTwGrEPtUderBYXx7ShUmPfnxnqscw=
|
||||
github.com/uptrace/bun/dialect/pgdialect v0.4.3 h1:lM2IUKpU99110chKkupw3oTfXiOKpB0hTJIe6frqQDo=
|
||||
github.com/uptrace/bun/dialect/pgdialect v0.4.3/go.mod h1:BaNvWejl32oKUhwpFkw/eNcWldzIlVY4nfw/sNul0s8=
|
||||
github.com/uptrace/bun/driver/pgdriver v0.4.3 h1:WLtUL3xtnZuryRcXII8PV8dm6UfEMWQniHFmV5T4tEw=
|
||||
github.com/uptrace/bun/driver/pgdriver v0.4.3/go.mod h1:CQsGmzHK9Sq70avzRy7aFYAomoT3XihjGPtRDSToV+0=
|
||||
github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M=
|
||||
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
|
|
@ -391,13 +457,8 @@ github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyC
|
|||
github.com/valyala/fasthttp v1.14.0 h1:67bfuW9azCMwW/Jlq/C+VeihNpAuJMWkYPBig1gdi3A=
|
||||
github.com/valyala/fasthttp v1.14.0/go.mod h1:ol1PCaL0dX20wC0htZ7sYCsvCYmrouYra0zHzaclZhE=
|
||||
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
|
||||
github.com/vmihailenco/bufpool v0.1.11 h1:gOq2WmBrq0i2yW5QJ16ykccQ4wH9UyEsgLm6czKAd94=
|
||||
github.com/vmihailenco/bufpool v0.1.11/go.mod h1:AFf/MOy3l2CFTKbxwt0mp2MwnqjNEs5H/UxrkA5jxTQ=
|
||||
github.com/vmihailenco/msgpack/v5 v5.3.1/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc=
|
||||
github.com/vmihailenco/msgpack/v5 v5.3.4 h1:qMKAwOV+meBw2Y8k9cVwAy7qErtYCwBzZ2ellBfvnqc=
|
||||
github.com/vmihailenco/msgpack/v5 v5.3.4/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc=
|
||||
github.com/vmihailenco/tagparser v0.1.2 h1:gnjoVuB/kljJ5wICEEOpx98oXMWPLj22G67Vbd1qPqc=
|
||||
github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
|
||||
github.com/wagslane/go-password-validator v0.3.0 h1:vfxOPzGHkz5S146HDpavl0cw1DSVP061Ry2PX0/ON6I=
|
||||
|
|
@ -418,23 +479,36 @@ github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZ
|
|||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||
go.uber.org/goleak v0.10.0 h1:G3eWbSNIskeRqtsN/1uI5B+eP73y3JUuBsv9AZjehb4=
|
||||
go.uber.org/goleak v0.10.0/go.mod h1:VCZuO8V8mFPlL0F5J5GK1rtHV3DrFcQ1R8ryq7FK0aI=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
|
||||
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
|
||||
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
|
||||
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
|
||||
golang.org/x/crypto v0.0.0-20180527072434-ab813273cd59/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20180910181607-0e37d006457b/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-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI=
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
|
|
@ -481,6 +555,7 @@ golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR
|
|||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
|
|
@ -498,11 +573,8 @@ golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/
|
|||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q=
|
||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
|
|
@ -520,14 +592,17 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
|
|||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180525142821-c11f84a56e43/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
|
@ -557,17 +632,15 @@ golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
|
@ -575,6 +648,7 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
|||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
|
|
@ -588,14 +662,18 @@ golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3
|
|||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
|
|
@ -603,6 +681,7 @@ golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtn
|
|||
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
|
|
@ -621,8 +700,9 @@ golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roY
|
|||
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
|
@ -709,16 +789,15 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
|
|||
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/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
|
||||
gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
|
||||
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
|
||||
gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w=
|
||||
gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
|
|
@ -739,8 +818,6 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
|
|||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
mellium.im/sasl v0.2.1 h1:nspKSRg7/SyO0cRGY71OkfHab8tf9kCts6a6oTDut0w=
|
||||
mellium.im/sasl v0.2.1/go.mod h1:ROaEDLQNuf9vjKqE1SrAfnsobm2YKXT1gnN1uDp1PjQ=
|
||||
mvdan.cc/xurls/v2 v2.3.0 h1:59Olnbt67UKpxF1EwVBopJvkSUBmgtb468E4GVWIZ1I=
|
||||
mvdan.cc/xurls/v2 v2.3.0/go.mod h1:AjuTy7gEiUArFMjgBBDU4SMxlfUYsRokpJQgNWOt3e4=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ var Start cliactions.GTSAction = func(ctx context.Context, c *config.Config, log
|
|||
transportController := transport.NewController(c, dbService, &federation.Clock{}, http.DefaultClient, log)
|
||||
federator := federation.NewFederator(dbService, federatingDB, transportController, c, log, typeConverter, mediaHandler)
|
||||
processor := processing.NewProcessor(c, typeConverter, federator, oauthServer, mediaHandler, storageBackend, timelineManager, dbService, log)
|
||||
if err := processor.Start(); err != nil {
|
||||
if err := processor.Start(ctx); err != nil {
|
||||
return fmt.Errorf("error starting processor: %s", err)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ var Start cliactions.GTSAction = func(ctx context.Context, _ *config.Config, log
|
|||
federator := testrig.NewTestFederator(dbService, transportController, storageBackend)
|
||||
|
||||
processor := testrig.NewTestProcessor(dbService, storageBackend, federator)
|
||||
if err := processor.Start(); err != nil {
|
||||
if err := processor.Start(ctx); err != nil {
|
||||
return fmt.Errorf("error starting processor: %s", err)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -250,7 +250,7 @@ func (a *adminDB) CreateInstanceAccount(ctx context.Context) db.Error {
|
|||
return err
|
||||
}
|
||||
|
||||
a.log.Infof("instance account CREATED with id %s", username, acct.ID)
|
||||
a.log.Infof("instance account %s CREATED with id %s", username, acct.ID)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ func (b *basicDB) CreateTable(ctx context.Context, i interface{}) db.Error {
|
|||
}
|
||||
|
||||
func (b *basicDB) DropTable(ctx context.Context, i interface{}) db.Error {
|
||||
_, err := b.conn.NewDropTable().Model(i).Exec(ctx)
|
||||
_, err := b.conn.NewDropTable().IfExists().Model(i).Exec(ctx)
|
||||
return processErrorResponse(err)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,21 +42,13 @@ func (d *domainDB) IsDomainBlocked(ctx context.Context, domain string) (bool, db
|
|||
return false, nil
|
||||
}
|
||||
|
||||
count, err := d.conn.
|
||||
q := d.conn.
|
||||
NewSelect().
|
||||
Model(>smodel.DomainBlock{}).
|
||||
Where("LOWER(domain) = LOWER(?)", domain).
|
||||
Limit(1).
|
||||
Count(ctx)
|
||||
Limit(1)
|
||||
|
||||
blocked := count != 0
|
||||
err = processErrorResponse(err)
|
||||
|
||||
if err != db.ErrNoEntries {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return blocked, nil
|
||||
return exists(ctx, q)
|
||||
}
|
||||
|
||||
func (d *domainDB) AreDomainsBlocked(ctx context.Context, domains []string) (bool, db.Error) {
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/jackc/pgx/v4"
|
||||
"github.com/jackc/pgx/v4/stdlib"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/config"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||
|
|
@ -37,7 +39,6 @@ import (
|
|||
"github.com/superseriousbusiness/gotosocial/internal/id"
|
||||
"github.com/uptrace/bun"
|
||||
"github.com/uptrace/bun/dialect/pgdialect"
|
||||
"github.com/uptrace/bun/driver/pgdriver"
|
||||
)
|
||||
|
||||
var registerTables []interface{} = []interface{}{
|
||||
|
|
@ -67,19 +68,13 @@ type postgresService struct {
|
|||
// NewPostgresService returns a postgresService derived from the provided config, which implements the go-fed DB interface.
|
||||
// Under the hood, it uses https://github.com/go-pg/pg to create and maintain a database connection.
|
||||
func NewPostgresService(ctx context.Context, c *config.Config, log *logrus.Logger) (db.DB, error) {
|
||||
for _, t := range registerTables {
|
||||
// https://pg.uptrace.dev/orm/many-to-many-relation/
|
||||
bun.RegisterModel(t)
|
||||
}
|
||||
|
||||
opts, err := derivePGOptions(c)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create postgres service: %s", err)
|
||||
return nil, fmt.Errorf("could not create postgres options: %s", err)
|
||||
}
|
||||
log.Debugf("using pg options: %+v", opts)
|
||||
|
||||
sqldb := sql.OpenDB(pgdriver.NewConnector(opts...))
|
||||
|
||||
log.Debugf("using opts %+v", opts)
|
||||
sqldb := stdlib.OpenDB(*opts)
|
||||
conn := bun.NewDB(sqldb, pgdialect.New())
|
||||
|
||||
// actually *begin* the connection so that we can tell if the db is there and listening
|
||||
|
|
@ -88,6 +83,12 @@ func NewPostgresService(ctx context.Context, c *config.Config, log *logrus.Logge
|
|||
}
|
||||
log.Info("connected to postgres")
|
||||
|
||||
for _, t := range registerTables {
|
||||
// https://bun.uptrace.dev/orm/many-to-many-relation/
|
||||
conn.RegisterModel(t)
|
||||
}
|
||||
log.Info("models registered")
|
||||
|
||||
ps := &postgresService{
|
||||
Account: &accountDB{
|
||||
config: c,
|
||||
|
|
@ -157,9 +158,9 @@ func NewPostgresService(ctx context.Context, c *config.Config, log *logrus.Logge
|
|||
HANDY STUFF
|
||||
*/
|
||||
|
||||
// derivePGOptions takes an application config and returns either a ready-to-use *pg.Options
|
||||
// derivePGOptions takes an application config and returns either a ready-to-use set of options
|
||||
// with sensible defaults, or an error if it's not satisfied by the provided config.
|
||||
func derivePGOptions(c *config.Config) ([]pgdriver.DriverOption, error) {
|
||||
func derivePGOptions(c *config.Config) (*pgx.ConnConfig, error) {
|
||||
if strings.ToUpper(c.DBConfig.Type) != db.DBTypePostgres {
|
||||
return nil, fmt.Errorf("expected db type of %s but got %s", db.DBTypePostgres, c.DBConfig.Type)
|
||||
}
|
||||
|
|
@ -237,18 +238,15 @@ func derivePGOptions(c *config.Config) ([]pgdriver.DriverOption, error) {
|
|||
tlsConfig.RootCAs = certPool
|
||||
}
|
||||
|
||||
// We can rely on the pg library we're using to set
|
||||
// sensible defaults for everything we don't set here.
|
||||
options := []pgdriver.DriverOption{
|
||||
pgdriver.WithAddr(fmt.Sprintf("%s:%d", c.DBConfig.Address, c.DBConfig.Port)),
|
||||
pgdriver.WithUser(c.DBConfig.User),
|
||||
pgdriver.WithPassword(c.DBConfig.Password),
|
||||
pgdriver.WithDatabase(c.DBConfig.Database),
|
||||
pgdriver.WithApplicationName(c.ApplicationName),
|
||||
pgdriver.WithTLSConfig(tlsConfig),
|
||||
}
|
||||
opts, _ := pgx.ParseConfig("")
|
||||
opts.Host = c.DBConfig.Address
|
||||
opts.Port = uint16(c.DBConfig.Port)
|
||||
opts.User = c.DBConfig.User
|
||||
opts.Password = c.DBConfig.Password
|
||||
opts.TLSConfig = tlsConfig
|
||||
opts.PreferSimpleProtocol = true
|
||||
|
||||
return options, nil
|
||||
return opts, nil
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -257,9 +255,9 @@ func derivePGOptions(c *config.Config) ([]pgdriver.DriverOption, error) {
|
|||
|
||||
// TODO: move these to the type converter, it's bananas that they're here and not there
|
||||
|
||||
func (ps *postgresService) MentionStringsToMentions(targetAccounts []string, originAccountID string, statusID string) ([]*gtsmodel.Mention, error) {
|
||||
func (ps *postgresService) MentionStringsToMentions(ctx context.Context, targetAccounts []string, originAccountID string, statusID string) ([]*gtsmodel.Mention, error) {
|
||||
ogAccount := >smodel.Account{}
|
||||
if err := ps.conn.Model(ogAccount).Where("id = ?", originAccountID).Select(); err != nil {
|
||||
if err := ps.conn.NewSelect().Model(ogAccount).Where("id = ?", originAccountID).Scan(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
@ -304,14 +302,14 @@ func (ps *postgresService) MentionStringsToMentions(targetAccounts []string, ori
|
|||
// match username + account, case insensitive
|
||||
if local {
|
||||
// local user -- should have a null domain
|
||||
err = ps.conn.Model(mentionedAccount).Where("LOWER(?) = LOWER(?)", pg.Ident("username"), username).Where("? IS NULL", pg.Ident("domain")).Select()
|
||||
err = ps.conn.NewSelect().Model(mentionedAccount).Where("LOWER(?) = LOWER(?)", bun.Ident("username"), username).Where("? IS NULL", bun.Ident("domain")).Scan(ctx)
|
||||
} else {
|
||||
// remote user -- should have domain defined
|
||||
err = ps.conn.Model(mentionedAccount).Where("LOWER(?) = LOWER(?)", pg.Ident("username"), username).Where("LOWER(?) = LOWER(?)", pg.Ident("domain"), domain).Select()
|
||||
err = ps.conn.NewSelect().Model(mentionedAccount).Where("LOWER(?) = LOWER(?)", bun.Ident("username"), username).Where("LOWER(?) = LOWER(?)", bun.Ident("domain"), domain).Scan(ctx)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
if err == pg.ErrNoRows {
|
||||
if err == sql.ErrNoRows {
|
||||
// no result found for this username/domain so just don't include it as a mencho and carry on about our business
|
||||
ps.log.Debugf("no account found with username '%s' and domain '%s', skipping it", username, domain)
|
||||
continue
|
||||
|
|
@ -335,14 +333,14 @@ func (ps *postgresService) MentionStringsToMentions(targetAccounts []string, ori
|
|||
return menchies, nil
|
||||
}
|
||||
|
||||
func (ps *postgresService) TagStringsToTags(tags []string, originAccountID string, statusID string) ([]*gtsmodel.Tag, error) {
|
||||
func (ps *postgresService) TagStringsToTags(ctx context.Context, tags []string, originAccountID string, statusID string) ([]*gtsmodel.Tag, error) {
|
||||
newTags := []*gtsmodel.Tag{}
|
||||
for _, t := range tags {
|
||||
tag := >smodel.Tag{}
|
||||
// we can use selectorinsert here to create the new tag if it doesn't exist already
|
||||
// inserted will be true if this is a new tag we just created
|
||||
if err := ps.conn.Model(tag).Where("LOWER(?) = LOWER(?)", pg.Ident("name"), t).Select(); err != nil {
|
||||
if err == pg.ErrNoRows {
|
||||
if err := ps.conn.NewSelect().Model(tag).Where("LOWER(?) = LOWER(?)", bun.Ident("name"), t).Scan(ctx); err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
// tag doesn't exist yet so populate it
|
||||
newID, err := id.NewRandomULID()
|
||||
if err != nil {
|
||||
|
|
@ -371,13 +369,13 @@ func (ps *postgresService) TagStringsToTags(tags []string, originAccountID strin
|
|||
return newTags, nil
|
||||
}
|
||||
|
||||
func (ps *postgresService) EmojiStringsToEmojis(emojis []string, originAccountID string, statusID string) ([]*gtsmodel.Emoji, error) {
|
||||
func (ps *postgresService) EmojiStringsToEmojis(ctx context.Context, emojis []string, originAccountID string, statusID string) ([]*gtsmodel.Emoji, error) {
|
||||
newEmojis := []*gtsmodel.Emoji{}
|
||||
for _, e := range emojis {
|
||||
emoji := >smodel.Emoji{}
|
||||
err := ps.conn.Model(emoji).Where("shortcode = ?", e).Where("visible_in_picker = true").Where("disabled = false").Select()
|
||||
err := ps.conn.NewSelect().Model(emoji).Where("shortcode = ?", e).Where("visible_in_picker = true").Where("disabled = false").Scan(ctx)
|
||||
if err != nil {
|
||||
if err == pg.ErrNoRows {
|
||||
if err == sql.ErrNoRows {
|
||||
// no result found for this username/domain so just don't include it as an emoji and carry on about our business
|
||||
ps.log.Debugf("no emoji found with shortcode %s, skipping it", e)
|
||||
continue
|
||||
|
|
|
|||
|
|
@ -67,16 +67,7 @@ func (r *relationshipDB) IsBlocked(ctx context.Context, account1 string, account
|
|||
Where("account_id = ?", account2)
|
||||
}
|
||||
|
||||
count, err := q.Count(ctx)
|
||||
|
||||
blocked := count != 0
|
||||
err = processErrorResponse(err)
|
||||
|
||||
if err != db.ErrNoEntries {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return blocked, nil
|
||||
return exists(ctx, q)
|
||||
}
|
||||
|
||||
func (r *relationshipDB) GetBlock(ctx context.Context, account1 string, account2 string) (*gtsmodel.Block, db.Error) {
|
||||
|
|
@ -186,16 +177,7 @@ func (r *relationshipDB) IsFollowing(ctx context.Context, sourceAccount *gtsmode
|
|||
Where("target_account_id = ?", targetAccount.ID).
|
||||
Limit(1)
|
||||
|
||||
count, err := q.Count(ctx)
|
||||
|
||||
following := count != 0
|
||||
err = processErrorResponse(err)
|
||||
|
||||
if err != db.ErrNoEntries {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return following, nil
|
||||
return exists(ctx, q)
|
||||
}
|
||||
|
||||
func (r *relationshipDB) IsFollowRequested(ctx context.Context, sourceAccount *gtsmodel.Account, targetAccount *gtsmodel.Account) (bool, db.Error) {
|
||||
|
|
@ -209,16 +191,7 @@ func (r *relationshipDB) IsFollowRequested(ctx context.Context, sourceAccount *g
|
|||
Where("account_id = ?", sourceAccount.ID).
|
||||
Where("target_account_id = ?", targetAccount.ID)
|
||||
|
||||
count, err := q.Count(ctx)
|
||||
|
||||
followRequested := count != 0
|
||||
err = processErrorResponse(err)
|
||||
|
||||
if err != db.ErrNoEntries {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return followRequested, nil
|
||||
return exists(ctx, q)
|
||||
}
|
||||
|
||||
func (r *relationshipDB) IsMutualFollowing(ctx context.Context, account1 *gtsmodel.Account, account2 *gtsmodel.Account) (bool, db.Error) {
|
||||
|
|
|
|||
|
|
@ -24,8 +24,6 @@ import (
|
|||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/go-pg/pg/v10"
|
||||
"github.com/go-pg/pg/v10/orm"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/cache"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/config"
|
||||
|
|
@ -71,8 +69,10 @@ func (s *statusDB) statusCached(id string) (*gtsmodel.Status, bool) {
|
|||
return status, true
|
||||
}
|
||||
|
||||
func (s *statusDB) newStatusQ(status interface{}) *orm.Query {
|
||||
return s.conn.Model(status).
|
||||
func (s *statusDB) newStatusQ(status interface{}) *bun.SelectQuery {
|
||||
return s.conn.
|
||||
NewSelect().
|
||||
Model(status).
|
||||
Relation("Attachments").
|
||||
Relation("Tags").
|
||||
Relation("Mentions").
|
||||
|
|
@ -85,14 +85,16 @@ func (s *statusDB) newStatusQ(status interface{}) *orm.Query {
|
|||
Relation("CreatedWithApplication")
|
||||
}
|
||||
|
||||
func (s *statusDB) newFaveQ(faves interface{}) *orm.Query {
|
||||
return s.conn.Model(faves).
|
||||
func (s *statusDB) newFaveQ(faves interface{}) *bun.SelectQuery {
|
||||
return s.conn.
|
||||
NewSelect().
|
||||
Model(faves).
|
||||
Relation("Account").
|
||||
Relation("TargetAccount").
|
||||
Relation("Status")
|
||||
}
|
||||
|
||||
func (s *statusDB) GetStatusByID(id string) (*gtsmodel.Status, db.Error) {
|
||||
func (s *statusDB) GetStatusByID(ctx context.Context, id string) (*gtsmodel.Status, db.Error) {
|
||||
if status, cached := s.statusCached(id); cached {
|
||||
return status, nil
|
||||
}
|
||||
|
|
@ -102,7 +104,7 @@ func (s *statusDB) GetStatusByID(id string) (*gtsmodel.Status, db.Error) {
|
|||
q := s.newStatusQ(status).
|
||||
Where("status.id = ?", id)
|
||||
|
||||
err := processErrorResponse(q.Select())
|
||||
err := processErrorResponse(q.Scan(ctx))
|
||||
|
||||
if err == nil && status != nil {
|
||||
s.cacheStatus(id, status)
|
||||
|
|
@ -111,7 +113,7 @@ func (s *statusDB) GetStatusByID(id string) (*gtsmodel.Status, db.Error) {
|
|||
return status, err
|
||||
}
|
||||
|
||||
func (s *statusDB) GetStatusByURI(uri string) (*gtsmodel.Status, db.Error) {
|
||||
func (s *statusDB) GetStatusByURI(ctx context.Context, uri string) (*gtsmodel.Status, db.Error) {
|
||||
if status, cached := s.statusCached(uri); cached {
|
||||
return status, nil
|
||||
}
|
||||
|
|
@ -121,7 +123,7 @@ func (s *statusDB) GetStatusByURI(uri string) (*gtsmodel.Status, db.Error) {
|
|||
q := s.newStatusQ(status).
|
||||
Where("LOWER(status.uri) = LOWER(?)", uri)
|
||||
|
||||
err := processErrorResponse(q.Select())
|
||||
err := processErrorResponse(q.Scan(ctx))
|
||||
|
||||
if err == nil && status != nil {
|
||||
s.cacheStatus(uri, status)
|
||||
|
|
@ -130,7 +132,7 @@ func (s *statusDB) GetStatusByURI(uri string) (*gtsmodel.Status, db.Error) {
|
|||
return status, err
|
||||
}
|
||||
|
||||
func (s *statusDB) GetStatusByURL(uri string) (*gtsmodel.Status, db.Error) {
|
||||
func (s *statusDB) GetStatusByURL(ctx context.Context, uri string) (*gtsmodel.Status, db.Error) {
|
||||
if status, cached := s.statusCached(uri); cached {
|
||||
return status, nil
|
||||
}
|
||||
|
|
@ -140,7 +142,7 @@ func (s *statusDB) GetStatusByURL(uri string) (*gtsmodel.Status, db.Error) {
|
|||
q := s.newStatusQ(status).
|
||||
Where("LOWER(status.url) = LOWER(?)", uri)
|
||||
|
||||
err := processErrorResponse(q.Select())
|
||||
err := processErrorResponse(q.Scan(ctx))
|
||||
|
||||
if err == nil && status != nil {
|
||||
s.cacheStatus(uri, status)
|
||||
|
|
@ -149,24 +151,24 @@ func (s *statusDB) GetStatusByURL(uri string) (*gtsmodel.Status, db.Error) {
|
|||
return status, err
|
||||
}
|
||||
|
||||
func (s *statusDB) PutStatus(status *gtsmodel.Status) db.Error {
|
||||
transaction := func(tx *pg.Tx) error {
|
||||
func (s *statusDB) PutStatus(ctx context.Context, status *gtsmodel.Status) db.Error {
|
||||
transaction := func(ctx context.Context, tx bun.Tx) error {
|
||||
// create links between this status and any emojis it uses
|
||||
for _, i := range status.EmojiIDs {
|
||||
if _, err := tx.Model(>smodel.StatusToEmoji{
|
||||
if _, err := tx.NewInsert().Model(>smodel.StatusToEmoji{
|
||||
StatusID: status.ID,
|
||||
EmojiID: i,
|
||||
}).Insert(); err != nil {
|
||||
}).Exec(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// create links between this status and any tags it uses
|
||||
for _, i := range status.TagIDs {
|
||||
if _, err := tx.Model(>smodel.StatusToTag{
|
||||
if _, err := tx.NewInsert().Model(>smodel.StatusToTag{
|
||||
StatusID: status.ID,
|
||||
TagID: i,
|
||||
}).Insert(); err != nil {
|
||||
}).Exec(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
@ -175,33 +177,33 @@ func (s *statusDB) PutStatus(status *gtsmodel.Status) db.Error {
|
|||
for _, a := range status.Attachments {
|
||||
a.StatusID = status.ID
|
||||
a.UpdatedAt = time.Now()
|
||||
if _, err := s.conn.Model(a).
|
||||
if _, err := s.conn.NewUpdate().Model(a).
|
||||
Where("id = ?", a.ID).
|
||||
Update(); err != nil {
|
||||
Exec(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
_, err := tx.Model(status).Insert()
|
||||
_, err := tx.NewInsert().Model(status).Exec(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
return processErrorResponse(s.conn.RunInTransaction(context.Background(), transaction))
|
||||
return processErrorResponse(s.conn.RunInTx(ctx, nil, transaction))
|
||||
}
|
||||
|
||||
func (s *statusDB) GetStatusParents(status *gtsmodel.Status, onlyDirect bool) ([]*gtsmodel.Status, db.Error) {
|
||||
func (s *statusDB) GetStatusParents(ctx context.Context, status *gtsmodel.Status, onlyDirect bool) ([]*gtsmodel.Status, db.Error) {
|
||||
parents := []*gtsmodel.Status{}
|
||||
s.statusParent(status, &parents, onlyDirect)
|
||||
s.statusParent(ctx, status, &parents, onlyDirect)
|
||||
|
||||
return parents, nil
|
||||
}
|
||||
|
||||
func (s *statusDB) statusParent(status *gtsmodel.Status, foundStatuses *[]*gtsmodel.Status, onlyDirect bool) {
|
||||
func (s *statusDB) statusParent(ctx context.Context, status *gtsmodel.Status, foundStatuses *[]*gtsmodel.Status, onlyDirect bool) {
|
||||
if status.InReplyToID == "" {
|
||||
return
|
||||
}
|
||||
|
||||
parentStatus, err := s.GetStatusByID(status.InReplyToID)
|
||||
parentStatus, err := s.GetStatusByID(ctx, status.InReplyToID)
|
||||
if err == nil {
|
||||
*foundStatuses = append(*foundStatuses, parentStatus)
|
||||
}
|
||||
|
|
@ -210,13 +212,13 @@ func (s *statusDB) statusParent(status *gtsmodel.Status, foundStatuses *[]*gtsmo
|
|||
return
|
||||
}
|
||||
|
||||
s.statusParent(parentStatus, foundStatuses, false)
|
||||
s.statusParent(ctx, parentStatus, foundStatuses, false)
|
||||
}
|
||||
|
||||
func (s *statusDB) GetStatusChildren(status *gtsmodel.Status, onlyDirect bool, minID string) ([]*gtsmodel.Status, db.Error) {
|
||||
func (s *statusDB) GetStatusChildren(ctx context.Context, status *gtsmodel.Status, onlyDirect bool, minID string) ([]*gtsmodel.Status, db.Error) {
|
||||
foundStatuses := &list.List{}
|
||||
foundStatuses.PushFront(status)
|
||||
s.statusChildren(status, foundStatuses, onlyDirect, minID)
|
||||
s.statusChildren(ctx, status, foundStatuses, onlyDirect, minID)
|
||||
|
||||
children := []*gtsmodel.Status{}
|
||||
for e := foundStatuses.Front(); e != nil; e = e.Next() {
|
||||
|
|
@ -234,15 +236,18 @@ func (s *statusDB) GetStatusChildren(status *gtsmodel.Status, onlyDirect bool, m
|
|||
return children, nil
|
||||
}
|
||||
|
||||
func (s *statusDB) statusChildren(status *gtsmodel.Status, foundStatuses *list.List, onlyDirect bool, minID string) {
|
||||
func (s *statusDB) statusChildren(ctx context.Context, status *gtsmodel.Status, foundStatuses *list.List, onlyDirect bool, minID string) {
|
||||
immediateChildren := []*gtsmodel.Status{}
|
||||
|
||||
q := s.conn.Model(&immediateChildren).Where("in_reply_to_id = ?", status.ID)
|
||||
q := s.conn.
|
||||
NewSelect().
|
||||
Model(&immediateChildren).
|
||||
Where("in_reply_to_id = ?", status.ID)
|
||||
if minID != "" {
|
||||
q = q.Where("status.id > ?", minID)
|
||||
}
|
||||
|
||||
if err := q.Select(); err != nil {
|
||||
if err := q.Scan(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -264,56 +269,78 @@ func (s *statusDB) statusChildren(status *gtsmodel.Status, foundStatuses *list.L
|
|||
if onlyDirect {
|
||||
return
|
||||
}
|
||||
s.statusChildren(child, foundStatuses, false, minID)
|
||||
s.statusChildren(ctx, child, foundStatuses, false, minID)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *statusDB) CountStatusReplies(status *gtsmodel.Status) (int, db.Error) {
|
||||
return s.conn.Model(>smodel.Status{}).Where("in_reply_to_id = ?", status.ID).Count()
|
||||
func (s *statusDB) CountStatusReplies(ctx context.Context, status *gtsmodel.Status) (int, db.Error) {
|
||||
return s.conn.NewSelect().Model(>smodel.Status{}).Where("in_reply_to_id = ?", status.ID).Count(ctx)
|
||||
}
|
||||
|
||||
func (s *statusDB) CountStatusReblogs(status *gtsmodel.Status) (int, db.Error) {
|
||||
return s.conn.Model(>smodel.Status{}).Where("boost_of_id = ?", status.ID).Count()
|
||||
func (s *statusDB) CountStatusReblogs(ctx context.Context, status *gtsmodel.Status) (int, db.Error) {
|
||||
return s.conn.NewSelect().Model(>smodel.Status{}).Where("boost_of_id = ?", status.ID).Count(ctx)
|
||||
}
|
||||
|
||||
func (s *statusDB) CountStatusFaves(status *gtsmodel.Status) (int, db.Error) {
|
||||
return s.conn.Model(>smodel.StatusFave{}).Where("status_id = ?", status.ID).Count()
|
||||
func (s *statusDB) CountStatusFaves(ctx context.Context, status *gtsmodel.Status) (int, db.Error) {
|
||||
return s.conn.NewSelect().Model(>smodel.StatusFave{}).Where("status_id = ?", status.ID).Count(ctx)
|
||||
}
|
||||
|
||||
func (s *statusDB) IsStatusFavedBy(status *gtsmodel.Status, accountID string) (bool, db.Error) {
|
||||
return s.conn.Model(>smodel.StatusFave{}).Where("status_id = ?", status.ID).Where("account_id = ?", accountID).Exists()
|
||||
func (s *statusDB) IsStatusFavedBy(ctx context.Context, status *gtsmodel.Status, accountID string) (bool, db.Error) {
|
||||
q := s.conn.
|
||||
NewSelect().
|
||||
Model(>smodel.StatusFave{}).
|
||||
Where("status_id = ?", status.ID).
|
||||
Where("account_id = ?", accountID)
|
||||
|
||||
return exists(ctx, q)
|
||||
}
|
||||
|
||||
func (s *statusDB) IsStatusRebloggedBy(status *gtsmodel.Status, accountID string) (bool, db.Error) {
|
||||
return s.conn.Model(>smodel.Status{}).Where("boost_of_id = ?", status.ID).Where("account_id = ?", accountID).Exists()
|
||||
func (s *statusDB) IsStatusRebloggedBy(ctx context.Context, status *gtsmodel.Status, accountID string) (bool, db.Error) {
|
||||
q := s.conn.
|
||||
NewSelect().
|
||||
Model(>smodel.Status{}).
|
||||
Where("boost_of_id = ?", status.ID).
|
||||
Where("account_id = ?", accountID)
|
||||
|
||||
return exists(ctx, q)
|
||||
}
|
||||
|
||||
func (s *statusDB) IsStatusMutedBy(status *gtsmodel.Status, accountID string) (bool, db.Error) {
|
||||
return s.conn.Model(>smodel.StatusMute{}).Where("status_id = ?", status.ID).Where("account_id = ?", accountID).Exists()
|
||||
func (s *statusDB) IsStatusMutedBy(ctx context.Context, status *gtsmodel.Status, accountID string) (bool, db.Error) {
|
||||
q := s.conn.
|
||||
NewSelect().
|
||||
Model(>smodel.StatusMute{}).
|
||||
Where("status_id = ?", status.ID).
|
||||
Where("account_id = ?", accountID)
|
||||
|
||||
return exists(ctx, q)
|
||||
}
|
||||
|
||||
func (s *statusDB) IsStatusBookmarkedBy(status *gtsmodel.Status, accountID string) (bool, db.Error) {
|
||||
return s.conn.Model(>smodel.StatusBookmark{}).Where("status_id = ?", status.ID).Where("account_id = ?", accountID).Exists()
|
||||
func (s *statusDB) IsStatusBookmarkedBy(ctx context.Context, status *gtsmodel.Status, accountID string) (bool, db.Error) {
|
||||
q := s.conn.
|
||||
NewSelect().
|
||||
Model(>smodel.StatusBookmark{}).
|
||||
Where("status_id = ?", status.ID).
|
||||
Where("account_id = ?", accountID)
|
||||
|
||||
return exists(ctx, q)
|
||||
}
|
||||
|
||||
func (s *statusDB) GetStatusFaves(status *gtsmodel.Status) ([]*gtsmodel.StatusFave, db.Error) {
|
||||
func (s *statusDB) GetStatusFaves(ctx context.Context, status *gtsmodel.Status) ([]*gtsmodel.StatusFave, db.Error) {
|
||||
faves := []*gtsmodel.StatusFave{}
|
||||
|
||||
q := s.newFaveQ(&faves).
|
||||
Where("status_id = ?", status.ID)
|
||||
|
||||
err := processErrorResponse(q.Select())
|
||||
|
||||
err := processErrorResponse(q.Scan(ctx))
|
||||
return faves, err
|
||||
}
|
||||
|
||||
func (s *statusDB) GetStatusReblogs(status *gtsmodel.Status) ([]*gtsmodel.Status, db.Error) {
|
||||
func (s *statusDB) GetStatusReblogs(ctx context.Context, status *gtsmodel.Status) ([]*gtsmodel.Status, db.Error) {
|
||||
reblogs := []*gtsmodel.Status{}
|
||||
|
||||
q := s.newStatusQ(&reblogs).
|
||||
Where("boost_of_id = ?", status.ID)
|
||||
|
||||
err := processErrorResponse(q.Select())
|
||||
|
||||
err := processErrorResponse(q.Scan(ctx))
|
||||
return reblogs, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
package pg_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
|
@ -56,7 +57,7 @@ func (suite *StatusTestSuite) TearDownTest() {
|
|||
}
|
||||
|
||||
func (suite *StatusTestSuite) TestGetStatusByID() {
|
||||
status, err := suite.db.GetStatusByID(suite.testStatuses["local_account_1_status_1"].ID)
|
||||
status, err := suite.db.GetStatusByID(context.Background(), suite.testStatuses["local_account_1_status_1"].ID)
|
||||
if err != nil {
|
||||
suite.FailNow(err.Error())
|
||||
}
|
||||
|
|
@ -67,10 +68,11 @@ func (suite *StatusTestSuite) TestGetStatusByID() {
|
|||
suite.Nil(status.BoostOfAccount)
|
||||
suite.Nil(status.InReplyTo)
|
||||
suite.Nil(status.InReplyToAccount)
|
||||
suite.log.Debug("test finished")
|
||||
}
|
||||
|
||||
func (suite *StatusTestSuite) TestGetStatusByURI() {
|
||||
status, err := suite.db.GetStatusByURI(suite.testStatuses["local_account_1_status_1"].URI)
|
||||
status, err := suite.db.GetStatusByURI(context.Background(), suite.testStatuses["local_account_1_status_1"].URI)
|
||||
if err != nil {
|
||||
suite.FailNow(err.Error())
|
||||
}
|
||||
|
|
@ -84,7 +86,7 @@ func (suite *StatusTestSuite) TestGetStatusByURI() {
|
|||
}
|
||||
|
||||
func (suite *StatusTestSuite) TestGetStatusWithExtras() {
|
||||
status, err := suite.db.GetStatusByID(suite.testStatuses["admin_account_status_1"].ID)
|
||||
status, err := suite.db.GetStatusByID(context.Background(), suite.testStatuses["admin_account_status_1"].ID)
|
||||
if err != nil {
|
||||
suite.FailNow(err.Error())
|
||||
}
|
||||
|
|
@ -97,7 +99,7 @@ func (suite *StatusTestSuite) TestGetStatusWithExtras() {
|
|||
}
|
||||
|
||||
func (suite *StatusTestSuite) TestGetStatusWithMention() {
|
||||
status, err := suite.db.GetStatusByID(suite.testStatuses["local_account_2_status_5"].ID)
|
||||
status, err := suite.db.GetStatusByID(context.Background(), suite.testStatuses["local_account_2_status_5"].ID)
|
||||
if err != nil {
|
||||
suite.FailNow(err.Error())
|
||||
}
|
||||
|
|
@ -112,14 +114,14 @@ func (suite *StatusTestSuite) TestGetStatusWithMention() {
|
|||
|
||||
func (suite *StatusTestSuite) TestGetStatusTwice() {
|
||||
before1 := time.Now()
|
||||
_, err := suite.db.GetStatusByURI(suite.testStatuses["local_account_1_status_1"].URI)
|
||||
_, err := suite.db.GetStatusByURI(context.Background(), suite.testStatuses["local_account_1_status_1"].URI)
|
||||
suite.NoError(err)
|
||||
after1 := time.Now()
|
||||
duration1 := after1.Sub(before1)
|
||||
fmt.Println(duration1.Nanoseconds())
|
||||
|
||||
before2 := time.Now()
|
||||
_, err = suite.db.GetStatusByURI(suite.testStatuses["local_account_1_status_1"].URI)
|
||||
_, err = suite.db.GetStatusByURI(context.Background(), suite.testStatuses["local_account_1_status_1"].URI)
|
||||
suite.NoError(err)
|
||||
after2 := time.Now()
|
||||
duration2 := after2.Sub(before2)
|
||||
|
|
|
|||
|
|
@ -20,9 +20,9 @@ package pg
|
|||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"sort"
|
||||
|
||||
"github.com/go-pg/pg/v10"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/config"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||
|
|
@ -37,23 +37,27 @@ type timelineDB struct {
|
|||
cancel context.CancelFunc
|
||||
}
|
||||
|
||||
func (t *timelineDB) GetHomeTimeline(accountID string, maxID string, sinceID string, minID string, limit int, local bool) ([]*gtsmodel.Status, db.Error) {
|
||||
func (t *timelineDB) GetHomeTimeline(ctx context.Context, accountID string, maxID string, sinceID string, minID string, limit int, local bool) ([]*gtsmodel.Status, db.Error) {
|
||||
statuses := []*gtsmodel.Status{}
|
||||
q := t.conn.Model(&statuses)
|
||||
q := t.conn.
|
||||
NewSelect().
|
||||
Model(&statuses)
|
||||
|
||||
q = q.ColumnExpr("status.*").
|
||||
// Find out who accountID follows.
|
||||
Join("LEFT JOIN follows AS f ON f.target_account_id = status.account_id").
|
||||
// Use a WhereGroup here to specify that we want EITHER statuses posted by accounts that accountID follows,
|
||||
// OR statuses posted by accountID itself (since a user should be able to see their own statuses).
|
||||
//
|
||||
// This is equivalent to something like WHERE ... AND (... OR ...)
|
||||
// See: https://pg.uptrace.dev/queries/#select
|
||||
WhereGroup(func(q *pg.Query) (*pg.Query, error) {
|
||||
q = q.WhereOr("f.account_id = ?", accountID).
|
||||
whereGroup := func(*bun.SelectQuery) *bun.SelectQuery {
|
||||
q = q.Where("f.account_id = ?", accountID).
|
||||
WhereOr("status.account_id = ?", accountID)
|
||||
return q, nil
|
||||
}).
|
||||
return q
|
||||
}
|
||||
|
||||
q = q.ColumnExpr("status.*").
|
||||
// Find out who accountID follows.
|
||||
Join("LEFT JOIN follows AS f ON f.target_account_id = status.account_id").
|
||||
WhereGroup(" AND ", whereGroup).
|
||||
// Sort by highest ID (newest) to lowest ID (oldest)
|
||||
Order("status.id DESC")
|
||||
|
||||
|
|
@ -82,29 +86,19 @@ func (t *timelineDB) GetHomeTimeline(accountID string, maxID string, sinceID str
|
|||
q = q.Limit(limit)
|
||||
}
|
||||
|
||||
err := q.Select()
|
||||
if err != nil {
|
||||
if err == pg.ErrNoRows {
|
||||
return nil, db.ErrNoEntries
|
||||
}
|
||||
return nil, err
|
||||
return statuses, processErrorResponse(q.Scan(ctx))
|
||||
}
|
||||
|
||||
if len(statuses) == 0 {
|
||||
return nil, db.ErrNoEntries
|
||||
}
|
||||
|
||||
return statuses, nil
|
||||
}
|
||||
|
||||
func (t *timelineDB) GetPublicTimeline(accountID string, maxID string, sinceID string, minID string, limit int, local bool) ([]*gtsmodel.Status, db.Error) {
|
||||
func (t *timelineDB) GetPublicTimeline(ctx context.Context, accountID string, maxID string, sinceID string, minID string, limit int, local bool) ([]*gtsmodel.Status, db.Error) {
|
||||
statuses := []*gtsmodel.Status{}
|
||||
|
||||
q := t.conn.Model(&statuses).
|
||||
q := t.conn.
|
||||
NewSelect().
|
||||
Model(&statuses).
|
||||
Where("visibility = ?", gtsmodel.VisibilityPublic).
|
||||
Where("? IS NULL", pg.Ident("in_reply_to_id")).
|
||||
Where("? IS NULL", pg.Ident("in_reply_to_uri")).
|
||||
Where("? IS NULL", pg.Ident("boost_of_id")).
|
||||
Where("? IS NULL", bun.Ident("in_reply_to_id")).
|
||||
Where("? IS NULL", bun.Ident("in_reply_to_uri")).
|
||||
Where("? IS NULL", bun.Ident("boost_of_id")).
|
||||
Order("status.id DESC")
|
||||
|
||||
if maxID != "" {
|
||||
|
|
@ -127,28 +121,18 @@ func (t *timelineDB) GetPublicTimeline(accountID string, maxID string, sinceID s
|
|||
q = q.Limit(limit)
|
||||
}
|
||||
|
||||
err := q.Select()
|
||||
if err != nil {
|
||||
if err == pg.ErrNoRows {
|
||||
return nil, db.ErrNoEntries
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(statuses) == 0 {
|
||||
return nil, db.ErrNoEntries
|
||||
}
|
||||
|
||||
return statuses, nil
|
||||
return statuses, processErrorResponse(q.Scan(ctx))
|
||||
}
|
||||
|
||||
// TODO optimize this query and the logic here, because it's slow as balls -- it takes like a literal second to return with a limit of 20!
|
||||
// It might be worth serving it through a timeline instead of raw DB queries, like we do for Home feeds.
|
||||
func (t *timelineDB) GetFavedTimeline(accountID string, maxID string, minID string, limit int) ([]*gtsmodel.Status, string, string, db.Error) {
|
||||
func (t *timelineDB) GetFavedTimeline(ctx context.Context, accountID string, maxID string, minID string, limit int) ([]*gtsmodel.Status, string, string, db.Error) {
|
||||
|
||||
faves := []*gtsmodel.StatusFave{}
|
||||
|
||||
fq := t.conn.Model(&faves).
|
||||
fq := t.conn.
|
||||
NewSelect().
|
||||
Model(&faves).
|
||||
Where("account_id = ?", accountID).
|
||||
Order("id DESC")
|
||||
|
||||
|
|
@ -164,9 +148,9 @@ func (t *timelineDB) GetFavedTimeline(accountID string, maxID string, minID stri
|
|||
fq = fq.Limit(limit)
|
||||
}
|
||||
|
||||
err := fq.Select()
|
||||
err := fq.Scan(ctx)
|
||||
if err != nil {
|
||||
if err == pg.ErrNoRows {
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, "", "", db.ErrNoEntries
|
||||
}
|
||||
return nil, "", "", err
|
||||
|
|
@ -186,9 +170,13 @@ func (t *timelineDB) GetFavedTimeline(accountID string, maxID string, minID stri
|
|||
}
|
||||
|
||||
statuses := []*gtsmodel.Status{}
|
||||
err = t.conn.Model(&statuses).Where("id IN (?)", pg.In(in)).Select()
|
||||
err = t.conn.
|
||||
NewSelect().
|
||||
Model(&statuses).
|
||||
Where("id IN (?)", bun.In(in)).
|
||||
Scan(ctx)
|
||||
if err != nil {
|
||||
if err == pg.ErrNoRows {
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, "", "", db.ErrNoEntries
|
||||
}
|
||||
return nil, "", "", err
|
||||
|
|
|
|||
|
|
@ -1,11 +1,30 @@
|
|||
/*
|
||||
GoToSocial
|
||||
Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package pg
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"context"
|
||||
|
||||
"database/sql"
|
||||
|
||||
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
// processErrorResponse parses the given error and returns an appropriate DBError.
|
||||
|
|
@ -16,9 +35,40 @@ func processErrorResponse(err error) db.Error {
|
|||
case sql.ErrNoRows:
|
||||
return db.ErrNoEntries
|
||||
default:
|
||||
if strings.Contains(err.Error(), "duplicate key value violates unique constraint") {
|
||||
return db.ErrAlreadyExists
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
func exists(ctx context.Context, q *bun.SelectQuery) (bool, db.Error) {
|
||||
count, err := q.Count(ctx)
|
||||
|
||||
exists := count != 0
|
||||
|
||||
err = processErrorResponse(err)
|
||||
|
||||
if err != nil {
|
||||
if err == db.ErrNoEntries {
|
||||
return false, nil
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
|
||||
return exists, nil
|
||||
}
|
||||
|
||||
func notExists(ctx context.Context, q *bun.SelectQuery) (bool, db.Error) {
|
||||
count, err := q.Count(ctx)
|
||||
|
||||
notExists := count == 0
|
||||
|
||||
err = processErrorResponse(err)
|
||||
|
||||
if err != nil {
|
||||
if err == db.ErrNoEntries {
|
||||
return true, nil
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
|
||||
return notExists, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,24 +34,24 @@ type Account struct {
|
|||
*/
|
||||
|
||||
// id of this account in the local database
|
||||
ID string `pg:"type:CHAR(26),pk,notnull,unique"`
|
||||
ID string `bun:"type:CHAR(26),pk,notnull,unique"`
|
||||
// Username of the account, should just be a string of [a-z0-9_]. Can be added to domain to create the full username in the form ``[username]@[domain]`` eg., ``user_96@example.org``
|
||||
Username string `pg:",notnull,unique:userdomain"` // username and domain should be unique *with* each other
|
||||
Username string `bun:",notnull,unique:userdomain"` // username and domain should be unique *with* each other
|
||||
// Domain of the account, will be null if this is a local account, otherwise something like ``example.org`` or ``mastodon.social``. Should be unique with username.
|
||||
Domain string `pg:",unique:userdomain"` // username and domain should be unique *with* each other
|
||||
Domain string `bun:",unique:userdomain,nullzero"` // username and domain should be unique *with* each other
|
||||
|
||||
/*
|
||||
ACCOUNT METADATA
|
||||
*/
|
||||
|
||||
// ID of the avatar as a media attachment
|
||||
AvatarMediaAttachmentID string `pg:"type:CHAR(26)"`
|
||||
AvatarMediaAttachment *MediaAttachment `pg:"rel:has-one"`
|
||||
AvatarMediaAttachmentID string `bun:"type:CHAR(26)"`
|
||||
AvatarMediaAttachment *MediaAttachment `bun:"rel:belongs-to"`
|
||||
// For a non-local account, where can the header be fetched?
|
||||
AvatarRemoteURL string
|
||||
// ID of the header as a media attachment
|
||||
HeaderMediaAttachmentID string `pg:"type:CHAR(26)"`
|
||||
HeaderMediaAttachment *MediaAttachment `pg:"rel:has-one"`
|
||||
HeaderMediaAttachmentID string `bun:"type:CHAR(26)"`
|
||||
HeaderMediaAttachment *MediaAttachment `bun:"rel:belongs-to"`
|
||||
// For a non-local account, where can the header be fetched?
|
||||
HeaderRemoteURL string
|
||||
// DisplayName for this account. Can be empty, then just the Username will be used for display purposes.
|
||||
|
|
@ -63,11 +63,11 @@ type Account struct {
|
|||
// Is this a memorial account, ie., has the user passed away?
|
||||
Memorial bool
|
||||
// This account has moved this account id in the database
|
||||
MovedToAccountID string `pg:"type:CHAR(26)"`
|
||||
MovedToAccountID string `bun:"type:CHAR(26)"`
|
||||
// When was this account created?
|
||||
CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
|
||||
CreatedAt time.Time `bun:"type:timestamp,notnull,default:now()"`
|
||||
// When was this account last updated?
|
||||
UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
|
||||
UpdatedAt time.Time `bun:"type:timestamp,notnull,default:now()"`
|
||||
// Does this account identify itself as a bot?
|
||||
Bot bool
|
||||
// What reason was given for signing up when this account was created?
|
||||
|
|
@ -78,36 +78,36 @@ type Account struct {
|
|||
*/
|
||||
|
||||
// Does this account need an approval for new followers?
|
||||
Locked bool `pg:",default:true,use_zero"`
|
||||
Locked bool `bun:",default:true"`
|
||||
// Should this account be shown in the instance's profile directory?
|
||||
Discoverable bool `pg:",default:false"`
|
||||
Discoverable bool `bun:",default:false"`
|
||||
// Default post privacy for this account
|
||||
Privacy Visibility `pg:",default:'public'"`
|
||||
Privacy Visibility `bun:",default:'public'"`
|
||||
// Set posts from this account to sensitive by default?
|
||||
Sensitive bool `pg:",default:false"`
|
||||
Sensitive bool `bun:",default:false"`
|
||||
// What language does this account post in?
|
||||
Language string `pg:",default:'en'"`
|
||||
Language string `bun:",default:'en'"`
|
||||
|
||||
/*
|
||||
ACTIVITYPUB THINGS
|
||||
*/
|
||||
|
||||
// What is the activitypub URI for this account discovered by webfinger?
|
||||
URI string `pg:",unique"`
|
||||
URI string `bun:",unique"`
|
||||
// At which URL can we see the user account in a web browser?
|
||||
URL string `pg:",unique"`
|
||||
URL string `bun:",unique"`
|
||||
// Last time this account was located using the webfinger API.
|
||||
LastWebfingeredAt time.Time `pg:"type:timestamp"`
|
||||
LastWebfingeredAt time.Time `bun:"type:timestamp"`
|
||||
// Address of this account's activitypub inbox, for sending activity to
|
||||
InboxURI string `pg:",unique"`
|
||||
InboxURI string `bun:",unique"`
|
||||
// Address of this account's activitypub outbox
|
||||
OutboxURI string `pg:",unique"`
|
||||
OutboxURI string `bun:",unique"`
|
||||
// URI for getting the following list of this account
|
||||
FollowingURI string `pg:",unique"`
|
||||
FollowingURI string `bun:",unique"`
|
||||
// URI for getting the followers list of this account
|
||||
FollowersURI string `pg:",unique"`
|
||||
FollowersURI string `bun:",unique"`
|
||||
// URL for getting the featured collection list of this account
|
||||
FeaturedCollectionURI string `pg:",unique"`
|
||||
FeaturedCollectionURI string `bun:",unique"`
|
||||
// What type of activitypub actor is this account?
|
||||
ActorType string
|
||||
// This account is associated with x account id
|
||||
|
|
@ -129,15 +129,15 @@ type Account struct {
|
|||
*/
|
||||
|
||||
// When was this account set to have all its media shown as sensitive?
|
||||
SensitizedAt time.Time `pg:"type:timestamp"`
|
||||
SensitizedAt time.Time `bun:"type:timestamp"`
|
||||
// When was this account silenced (eg., statuses only visible to followers, not public)?
|
||||
SilencedAt time.Time `pg:"type:timestamp"`
|
||||
SilencedAt time.Time `bun:"type:timestamp"`
|
||||
// When was this account suspended (eg., don't allow it to log in/post, don't accept media/posts from this account)
|
||||
SuspendedAt time.Time `pg:"type:timestamp"`
|
||||
SuspendedAt time.Time `bun:"type:timestamp"`
|
||||
// Should we hide this account's collections?
|
||||
HideCollections bool
|
||||
// id of the database entry that caused this account to become suspended -- can be an account ID or a domain block ID
|
||||
SuspensionOrigin string `pg:"type:CHAR(26)"`
|
||||
SuspensionOrigin string `bun:"type:CHAR(26)"`
|
||||
}
|
||||
|
||||
// Field represents a key value field on an account, for things like pronouns, website, etc.
|
||||
|
|
@ -146,5 +146,5 @@ type Account struct {
|
|||
type Field struct {
|
||||
Name string
|
||||
Value string
|
||||
VerifiedAt time.Time `pg:"type:timestamp"`
|
||||
VerifiedAt time.Time `bun:"type:timestamp"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ package gtsmodel
|
|||
// It is used to authorize tokens etc, and is associated with an oauth client id in the database.
|
||||
type Application struct {
|
||||
// id of this application in the db
|
||||
ID string `pg:"type:CHAR(26),pk,notnull"`
|
||||
ID string `bun:"type:CHAR(26),pk,notnull"`
|
||||
// name of the application given when it was created (eg., 'tusky')
|
||||
Name string
|
||||
// website for the application given when it was created (eg., 'https://tusky.app')
|
||||
|
|
@ -30,7 +30,7 @@ type Application struct {
|
|||
// redirect uri requested by the application for oauth2 flow
|
||||
RedirectURI string
|
||||
// id of the associated oauth client entity in the db
|
||||
ClientID string `pg:"type:CHAR(26)"`
|
||||
ClientID string `bun:"type:CHAR(26)"`
|
||||
// secret of the associated oauth client entity in the db
|
||||
ClientSecret string
|
||||
// scopes requested when this app was created
|
||||
|
|
|
|||
|
|
@ -5,17 +5,17 @@ import "time"
|
|||
// Block refers to the blocking of one account by another.
|
||||
type Block struct {
|
||||
// id of this block in the database
|
||||
ID string `pg:"type:CHAR(26),pk,notnull"`
|
||||
ID string `bun:"type:CHAR(26),pk,notnull"`
|
||||
// When was this block created
|
||||
CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
|
||||
CreatedAt time.Time `bun:"type:timestamp,notnull,default:now()"`
|
||||
// When was this block updated
|
||||
UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
|
||||
UpdatedAt time.Time `bun:"type:timestamp,notnull,default:now()"`
|
||||
// Who created this block?
|
||||
AccountID string `pg:"type:CHAR(26),notnull"`
|
||||
Account *Account `pg:"rel:has-one"`
|
||||
AccountID string `bun:"type:CHAR(26),notnull"`
|
||||
Account *Account `bun:"rel:belongs-to"`
|
||||
// Who is targeted by this block?
|
||||
TargetAccountID string `pg:"type:CHAR(26),notnull"`
|
||||
TargetAccount *Account `pg:"rel:has-one"`
|
||||
TargetAccountID string `bun:"type:CHAR(26),notnull"`
|
||||
TargetAccount *Account `bun:"rel:belongs-to"`
|
||||
// Activitypub URI for this block
|
||||
URI string `pg:",notnull"`
|
||||
URI string `bun:",notnull"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,16 +23,16 @@ import "time"
|
|||
// DomainBlock represents a federation block against a particular domain
|
||||
type DomainBlock struct {
|
||||
// ID of this block in the database
|
||||
ID string `pg:"type:CHAR(26),pk,notnull,unique"`
|
||||
ID string `bun:"type:CHAR(26),pk,notnull,unique"`
|
||||
// blocked domain
|
||||
Domain string `pg:",pk,notnull,unique"`
|
||||
Domain string `bun:",pk,notnull,unique"`
|
||||
// When was this block created
|
||||
CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
|
||||
CreatedAt time.Time `bun:"type:timestamp,notnull,default:now()"`
|
||||
// When was this block updated
|
||||
UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
|
||||
UpdatedAt time.Time `bun:"type:timestamp,notnull,default:now()"`
|
||||
// Account ID of the creator of this block
|
||||
CreatedByAccountID string `pg:"type:CHAR(26),notnull"`
|
||||
CreatedByAccount *Account `pg:"rel:belongs-to"`
|
||||
CreatedByAccountID string `bun:"type:CHAR(26),notnull"`
|
||||
CreatedByAccount *Account `bun:"rel:belongs-to"`
|
||||
// Private comment on this block, viewable to admins
|
||||
PrivateComment string
|
||||
// Public comment on this block, viewable (optionally) by everyone
|
||||
|
|
@ -40,5 +40,5 @@ type DomainBlock struct {
|
|||
// whether the domain name should appear obfuscated when displaying it publicly
|
||||
Obfuscate bool
|
||||
// if this block was created through a subscription, what's the subscription ID?
|
||||
SubscriptionID string `pg:"type:CHAR(26)"`
|
||||
SubscriptionID string `bun:"type:CHAR(26)"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,14 +23,14 @@ import "time"
|
|||
// EmailDomainBlock represents a domain that the server should automatically reject sign-up requests from.
|
||||
type EmailDomainBlock struct {
|
||||
// ID of this block in the database
|
||||
ID string `pg:"type:CHAR(26),pk,notnull,unique"`
|
||||
ID string `bun:"type:CHAR(26),pk,notnull,unique"`
|
||||
// Email domain to block. Eg. 'gmail.com' or 'hotmail.com'
|
||||
Domain string `pg:",notnull"`
|
||||
Domain string `bun:",notnull"`
|
||||
// When was this block created
|
||||
CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
|
||||
CreatedAt time.Time `bun:"type:timestamp,notnull,default:now()"`
|
||||
// When was this block updated
|
||||
UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
|
||||
UpdatedAt time.Time `bun:"type:timestamp,notnull,default:now()"`
|
||||
// Account ID of the creator of this block
|
||||
CreatedByAccountID string `pg:"type:CHAR(26),notnull"`
|
||||
CreatedByAccount *Account `pg:"rel:belongs-to"`
|
||||
CreatedByAccountID string `bun:"type:CHAR(26),notnull"`
|
||||
CreatedByAccount *Account `bun:"rel:belongs-to"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,16 +23,16 @@ import "time"
|
|||
// Emoji represents a custom emoji that's been uploaded through the admin UI, and is useable by instance denizens.
|
||||
type Emoji struct {
|
||||
// database ID of this emoji
|
||||
ID string `pg:"type:CHAR(26),pk,notnull"`
|
||||
ID string `bun:"type:CHAR(26),pk,notnull"`
|
||||
// String shortcode for this emoji -- the part that's between colons. This should be lowercase a-z_
|
||||
// eg., 'blob_hug' 'purple_heart' Must be unique with domain.
|
||||
Shortcode string `pg:",notnull,unique:shortcodedomain"`
|
||||
Shortcode string `bun:",notnull,unique:shortcodedomain"`
|
||||
// Origin domain of this emoji, eg 'example.org', 'queer.party'. empty string for local emojis.
|
||||
Domain string `pg:",notnull,default:'',use_zero,unique:shortcodedomain"`
|
||||
Domain string `bun:",notnull,default:'',use_zero,unique:shortcodedomain"`
|
||||
// When was this emoji created. Must be unique with shortcode.
|
||||
CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
|
||||
CreatedAt time.Time `bun:"type:timestamp,notnull,default:now()"`
|
||||
// When was this emoji updated
|
||||
UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
|
||||
UpdatedAt time.Time `bun:"type:timestamp,notnull,default:now()"`
|
||||
// Where can this emoji be retrieved remotely? Null for local emojis.
|
||||
// For remote emojis, it'll be something like:
|
||||
// https://hackers.town/system/custom_emojis/images/000/049/842/original/1b74481204feabfd.png
|
||||
|
|
@ -51,28 +51,28 @@ type Emoji struct {
|
|||
ImageStaticURL string
|
||||
// Path of the emoji image in the server storage system. Will be something like:
|
||||
// '/gotosocial/storage/6339820e-ef65-4166-a262-5a9f46adb1a7/emoji/original/bfa6c9c5-6c25-4ea4-98b4-d78b8126fb52.png'
|
||||
ImagePath string `pg:",notnull"`
|
||||
ImagePath string `bun:",notnull"`
|
||||
// Path of a static version of the emoji image in the server storage system. Will be something like:
|
||||
// '/gotosocial/storage/6339820e-ef65-4166-a262-5a9f46adb1a7/emoji/small/bfa6c9c5-6c25-4ea4-98b4-d78b8126fb52.png'
|
||||
ImageStaticPath string `pg:",notnull"`
|
||||
ImageStaticPath string `bun:",notnull"`
|
||||
// MIME content type of the emoji image
|
||||
// Probably "image/png"
|
||||
ImageContentType string `pg:",notnull"`
|
||||
ImageContentType string `bun:",notnull"`
|
||||
// MIME content type of the static version of the emoji image.
|
||||
ImageStaticContentType string `pg:",notnull"`
|
||||
ImageStaticContentType string `bun:",notnull"`
|
||||
// Size of the emoji image file in bytes, for serving purposes.
|
||||
ImageFileSize int `pg:",notnull"`
|
||||
ImageFileSize int `bun:",notnull"`
|
||||
// Size of the static version of the emoji image file in bytes, for serving purposes.
|
||||
ImageStaticFileSize int `pg:",notnull"`
|
||||
ImageStaticFileSize int `bun:",notnull"`
|
||||
// When was the emoji image last updated?
|
||||
ImageUpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
|
||||
ImageUpdatedAt time.Time `bun:"type:timestamp,notnull,default:now()"`
|
||||
// Has a moderation action disabled this emoji from being shown?
|
||||
Disabled bool `pg:",notnull,default:false"`
|
||||
Disabled bool `bun:",notnull,default:false"`
|
||||
// ActivityStreams uri of this emoji. Something like 'https://example.org/emojis/1234'
|
||||
URI string `pg:",notnull,unique"`
|
||||
URI string `bun:",notnull,unique"`
|
||||
// Is this emoji visible in the admin emoji picker?
|
||||
VisibleInPicker bool `pg:",notnull,default:true"`
|
||||
VisibleInPicker bool `bun:",notnull,default:true"`
|
||||
// In which emoji category is this emoji visible?
|
||||
CategoryID string `pg:"type:CHAR(26)"`
|
||||
Status *Status `pg:"rel:belongs-to"`
|
||||
CategoryID string `bun:"type:CHAR(26)"`
|
||||
Status *Status `bun:"rel:belongs-to"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,21 +23,21 @@ import "time"
|
|||
// Follow represents one account following another, and the metadata around that follow.
|
||||
type Follow struct {
|
||||
// id of this follow in the database
|
||||
ID string `pg:"type:CHAR(26),pk,notnull,unique"`
|
||||
ID string `bun:"type:CHAR(26),pk,notnull,unique"`
|
||||
// When was this follow created?
|
||||
CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
|
||||
CreatedAt time.Time `bun:"type:timestamp,notnull,default:now()"`
|
||||
// When was this follow last updated?
|
||||
UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
|
||||
UpdatedAt time.Time `bun:"type:timestamp,notnull,default:now()"`
|
||||
// Who does this follow belong to?
|
||||
AccountID string `pg:"type:CHAR(26),unique:srctarget,notnull"`
|
||||
Account *Account `pg:"rel:belongs-to"`
|
||||
AccountID string `bun:"type:CHAR(26),unique:srctarget,notnull"`
|
||||
Account *Account `bun:"rel:belongs-to"`
|
||||
// Who does AccountID follow?
|
||||
TargetAccountID string `pg:"type:CHAR(26),unique:srctarget,notnull"`
|
||||
TargetAccount *Account `pg:"rel:has-one"`
|
||||
TargetAccountID string `bun:"type:CHAR(26),unique:srctarget,notnull"`
|
||||
TargetAccount *Account `bun:"rel:belongs-to"`
|
||||
// Does this follow also want to see reblogs and not just posts?
|
||||
ShowReblogs bool `pg:"default:true"`
|
||||
ShowReblogs bool `bun:"default:true"`
|
||||
// What is the activitypub URI of this follow?
|
||||
URI string `pg:",unique"`
|
||||
URI string `bun:",unique"`
|
||||
// does the following account want to be notified when the followed account posts?
|
||||
Notify bool
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,21 +23,21 @@ import "time"
|
|||
// FollowRequest represents one account requesting to follow another, and the metadata around that request.
|
||||
type FollowRequest struct {
|
||||
// id of this follow request in the database
|
||||
ID string `pg:"type:CHAR(26),pk,notnull,unique"`
|
||||
ID string `bun:"type:CHAR(26),pk,notnull,unique"`
|
||||
// When was this follow request created?
|
||||
CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
|
||||
CreatedAt time.Time `bun:"type:timestamp,notnull,default:now()"`
|
||||
// When was this follow request last updated?
|
||||
UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
|
||||
UpdatedAt time.Time `bun:"type:timestamp,notnull,default:now()"`
|
||||
// Who does this follow request originate from?
|
||||
AccountID string `pg:"type:CHAR(26),unique:srctarget,notnull"`
|
||||
Account Account `pg:"rel:has-one"`
|
||||
AccountID string `bun:"type:CHAR(26),unique:srctarget,notnull"`
|
||||
Account Account `bun:"rel:belongs-to"`
|
||||
// Who is the target of this follow request?
|
||||
TargetAccountID string `pg:"type:CHAR(26),unique:srctarget,notnull"`
|
||||
TargetAccount Account `pg:"rel:has-one"`
|
||||
TargetAccountID string `bun:"type:CHAR(26),unique:srctarget,notnull"`
|
||||
TargetAccount Account `bun:"rel:belongs-to"`
|
||||
// Does this follow also want to see reblogs and not just posts?
|
||||
ShowReblogs bool `pg:"default:true"`
|
||||
ShowReblogs bool `bun:"default:true"`
|
||||
// What is the activitypub URI of this follow request?
|
||||
URI string `pg:",unique"`
|
||||
URI string `bun:",unique"`
|
||||
// does the following account want to be notified when the followed account posts?
|
||||
Notify bool
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,22 +5,22 @@ import "time"
|
|||
// Instance represents a federated instance, either local or remote.
|
||||
type Instance struct {
|
||||
// ID of this instance in the database
|
||||
ID string `pg:"type:CHAR(26),pk,notnull,unique"`
|
||||
ID string `bun:"type:CHAR(26),pk,notnull,unique"`
|
||||
// Instance domain eg example.org
|
||||
Domain string `pg:",pk,notnull,unique"`
|
||||
Domain string `bun:",pk,notnull,unique"`
|
||||
// Title of this instance as it would like to be displayed.
|
||||
Title string
|
||||
// base URI of this instance eg https://example.org
|
||||
URI string `pg:",notnull,unique"`
|
||||
URI string `bun:",notnull,unique"`
|
||||
// When was this instance created in the db?
|
||||
CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
|
||||
CreatedAt time.Time `bun:"type:timestamp,notnull,default:now()"`
|
||||
// When was this instance last updated in the db?
|
||||
UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
|
||||
UpdatedAt time.Time `bun:"type:timestamp,notnull,default:now()"`
|
||||
// When was this instance suspended, if at all?
|
||||
SuspendedAt time.Time
|
||||
// ID of any existing domain block for this instance in the database
|
||||
DomainBlockID string `pg:"type:CHAR(26)"`
|
||||
DomainBlock *DomainBlock `pg:"rel:has-one"`
|
||||
DomainBlockID string `bun:"type:CHAR(26)"`
|
||||
DomainBlock *DomainBlock `bun:"rel:belongs-to"`
|
||||
// Short description of this instance
|
||||
ShortDescription string
|
||||
// Longer description of this instance
|
||||
|
|
@ -32,10 +32,10 @@ type Instance struct {
|
|||
// Username of the contact account for this instance
|
||||
ContactAccountUsername string
|
||||
// Contact account ID in the database for this instance
|
||||
ContactAccountID string `pg:"type:CHAR(26)"`
|
||||
ContactAccount *Account `pg:"rel:has-one"`
|
||||
ContactAccountID string `bun:"type:CHAR(26)"`
|
||||
ContactAccount *Account `bun:"rel:belongs-to"`
|
||||
// Reputation score of this instance
|
||||
Reputation int64 `pg:",notnull,default:0"`
|
||||
Reputation int64 `bun:",notnull,default:0"`
|
||||
// Version of the software used on this instance
|
||||
Version string
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,28 +26,28 @@ import (
|
|||
// somewhere in storage and that can be retrieved and served by the router.
|
||||
type MediaAttachment struct {
|
||||
// ID of the attachment in the database
|
||||
ID string `pg:"type:CHAR(26),pk,notnull,unique"`
|
||||
ID string `bun:"type:CHAR(26),pk,notnull,unique"`
|
||||
// ID of the status to which this is attached
|
||||
StatusID string `pg:"type:CHAR(26)"`
|
||||
StatusID string `bun:"type:CHAR(26)"`
|
||||
// Where can the attachment be retrieved on *this* server
|
||||
URL string
|
||||
// Where can the attachment be retrieved on a remote server (empty for local media)
|
||||
RemoteURL string
|
||||
// When was the attachment created
|
||||
CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
|
||||
CreatedAt time.Time `bun:"type:timestamp,notnull,default:now()"`
|
||||
// When was the attachment last updated
|
||||
UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
|
||||
UpdatedAt time.Time `bun:"type:timestamp,notnull,default:now()"`
|
||||
// Type of file (image/gif/audio/video)
|
||||
Type FileType `pg:",notnull"`
|
||||
Type FileType `bun:",notnull"`
|
||||
// Metadata about the file
|
||||
FileMeta FileMeta
|
||||
// To which account does this attachment belong
|
||||
AccountID string `pg:"type:CHAR(26),notnull"`
|
||||
Account *Account `pg:"rel:belongs-to"`
|
||||
AccountID string `bun:"type:CHAR(26),notnull"`
|
||||
Account *Account `bun:"rel:belongs-to"`
|
||||
// Description of the attachment (for screenreaders)
|
||||
Description string
|
||||
// To which scheduled status does this attachment belong
|
||||
ScheduledStatusID string `pg:"type:CHAR(26)"`
|
||||
ScheduledStatusID string `bun:"type:CHAR(26)"`
|
||||
// What is the generated blurhash of this attachment
|
||||
Blurhash string
|
||||
// What is the processing status of this attachment
|
||||
|
|
@ -71,7 +71,7 @@ type File struct {
|
|||
// What is the size of the file in bytes.
|
||||
FileSize int
|
||||
// When was the file last updated.
|
||||
UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
|
||||
UpdatedAt time.Time `bun:"type:timestamp,notnull,default:now()"`
|
||||
}
|
||||
|
||||
// Thumbnail refers to a small image thumbnail derived from a larger image, video, or audio file.
|
||||
|
|
@ -83,7 +83,7 @@ type Thumbnail struct {
|
|||
// What is the size of the file in bytes
|
||||
FileSize int
|
||||
// When was the file last updated
|
||||
UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
|
||||
UpdatedAt time.Time `bun:"type:timestamp,notnull,default:now()"`
|
||||
// What is the URL of the thumbnail on the local server
|
||||
URL string
|
||||
// What is the remote URL of the thumbnail (empty for local media)
|
||||
|
|
|
|||
|
|
@ -23,22 +23,22 @@ import "time"
|
|||
// Mention refers to the 'tagging' or 'mention' of a user within a status.
|
||||
type Mention struct {
|
||||
// ID of this mention in the database
|
||||
ID string `pg:"type:CHAR(26),pk,notnull,unique"`
|
||||
ID string `bun:"type:CHAR(26),pk,notnull,unique"`
|
||||
// ID of the status this mention originates from
|
||||
StatusID string `pg:"type:CHAR(26),notnull"`
|
||||
Status *Status `pg:"rel:belongs-to"`
|
||||
StatusID string `bun:"type:CHAR(26),notnull"`
|
||||
Status *Status `bun:"rel:belongs-to"`
|
||||
// When was this mention created?
|
||||
CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
|
||||
CreatedAt time.Time `bun:"type:timestamp,notnull,default:now()"`
|
||||
// When was this mention last updated?
|
||||
UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
|
||||
UpdatedAt time.Time `bun:"type:timestamp,notnull,default:now()"`
|
||||
// What's the internal account ID of the originator of the mention?
|
||||
OriginAccountID string `pg:"type:CHAR(26),notnull"`
|
||||
OriginAccount *Account `pg:"rel:has-one"`
|
||||
OriginAccountID string `bun:"type:CHAR(26),notnull"`
|
||||
OriginAccount *Account `bun:"rel:belongs-to"`
|
||||
// What's the AP URI of the originator of the mention?
|
||||
OriginAccountURI string `pg:",notnull"`
|
||||
OriginAccountURI string `bun:",notnull"`
|
||||
// What's the internal account ID of the mention target?
|
||||
TargetAccountID string `pg:"type:CHAR(26),notnull"`
|
||||
TargetAccount *Account `pg:"rel:has-one"`
|
||||
TargetAccountID string `bun:"type:CHAR(26),notnull"`
|
||||
TargetAccount *Account `bun:"rel:belongs-to"`
|
||||
// Prevent this mention from generating a notification?
|
||||
Silent bool
|
||||
|
||||
|
|
@ -54,15 +54,15 @@ type Mention struct {
|
|||
// @whatever_username@example.org
|
||||
//
|
||||
// This will not be put in the database, it's just for convenience.
|
||||
NameString string `pg:"-"`
|
||||
NameString string `bun:"-"`
|
||||
// TargetAccountURI is the AP ID (uri) of the user mentioned.
|
||||
//
|
||||
// This will not be put in the database, it's just for convenience.
|
||||
TargetAccountURI string `pg:"-"`
|
||||
TargetAccountURI string `bun:"-"`
|
||||
// TargetAccountURL is the web url of the user mentioned.
|
||||
//
|
||||
// This will not be put in the database, it's just for convenience.
|
||||
TargetAccountURL string `pg:"-"`
|
||||
TargetAccountURL string `bun:"-"`
|
||||
// A pointer to the gtsmodel account of the mentioned account.
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,20 +23,20 @@ import "time"
|
|||
// Notification models an alert/notification sent to an account about something like a reblog, like, new follow request, etc.
|
||||
type Notification struct {
|
||||
// ID of this notification in the database
|
||||
ID string `pg:"type:CHAR(26),pk,notnull"`
|
||||
ID string `bun:"type:CHAR(26),pk,notnull"`
|
||||
// Type of this notification
|
||||
NotificationType NotificationType `pg:",notnull"`
|
||||
NotificationType NotificationType `bun:",notnull"`
|
||||
// Creation time of this notification
|
||||
CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
|
||||
CreatedAt time.Time `bun:"type:timestamp,notnull,default:now()"`
|
||||
// Which account does this notification target (ie., who will receive the notification?)
|
||||
TargetAccountID string `pg:"type:CHAR(26),notnull"`
|
||||
TargetAccount *Account `pg:"rel:has-one"`
|
||||
TargetAccountID string `bun:"type:CHAR(26),notnull"`
|
||||
TargetAccount *Account `bun:"rel:belongs-to"`
|
||||
// Which account performed the action that created this notification?
|
||||
OriginAccountID string `pg:"type:CHAR(26),notnull"`
|
||||
OriginAccount *Account `pg:"rel:has-one"`
|
||||
OriginAccountID string `bun:"type:CHAR(26),notnull"`
|
||||
OriginAccount *Account `bun:"rel:belongs-to"`
|
||||
// If the notification pertains to a status, what is the database ID of that status?
|
||||
StatusID string `pg:"type:CHAR(26)"`
|
||||
Status *Status `pg:"rel:has-one"`
|
||||
StatusID string `bun:"type:CHAR(26)"`
|
||||
Status *Status `bun:"rel:belongs-to"`
|
||||
// Has this notification been read already?
|
||||
Read bool
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ package gtsmodel
|
|||
|
||||
// RouterSession is used to store and retrieve settings for a router session.
|
||||
type RouterSession struct {
|
||||
ID string `pg:"type:CHAR(26),pk,notnull"`
|
||||
Auth []byte `pg:",notnull"`
|
||||
Crypt []byte `pg:",notnull"`
|
||||
ID string `bun:"type:CHAR(26),pk,notnull"`
|
||||
Auth []byte `bun:",notnull"`
|
||||
Crypt []byte `bun:",notnull"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,61 +25,61 @@ import (
|
|||
// Status represents a user-created 'post' or 'status' in the database, either remote or local
|
||||
type Status struct {
|
||||
// id of the status in the database
|
||||
ID string `pg:"type:CHAR(26),pk,notnull"`
|
||||
ID string `bun:"type:CHAR(26),pk,notnull"`
|
||||
// uri at which this status is reachable
|
||||
URI string `pg:",unique"`
|
||||
URI string `bun:",unique"`
|
||||
// web url for viewing this status
|
||||
URL string `pg:",unique"`
|
||||
URL string `bun:",unique"`
|
||||
// the html-formatted content of this status
|
||||
Content string
|
||||
// Database IDs of any media attachments associated with this status
|
||||
AttachmentIDs []string `pg:"attachments,array"`
|
||||
Attachments []*MediaAttachment `pg:"attached_media,rel:has-many"`
|
||||
AttachmentIDs []string `bun:"attachments,array"`
|
||||
Attachments []*MediaAttachment `bun:"attached_media,rel:has-many"`
|
||||
// Database IDs of any tags used in this status
|
||||
TagIDs []string `pg:"tags,array"`
|
||||
Tags []*Tag `pg:"attached_tags,many2many:status_to_tags"` // https://pg.uptrace.dev/orm/many-to-many-relation/
|
||||
TagIDs []string `bun:"tags,array"`
|
||||
Tags []*Tag `bun:"attached_tags,m2m:status_to_tags"` // https://pg.uptrace.dev/orm/many-to-many-relation/
|
||||
// Database IDs of any mentions in this status
|
||||
MentionIDs []string `pg:"mentions,array"`
|
||||
Mentions []*Mention `pg:"attached_mentions,rel:has-many"`
|
||||
MentionIDs []string `bun:"mentions,array"`
|
||||
Mentions []*Mention `bun:"attached_mentions,rel:has-many"`
|
||||
// Database IDs of any emojis used in this status
|
||||
EmojiIDs []string `pg:"emojis,array"`
|
||||
Emojis []*Emoji `pg:"attached_emojis,many2many:status_to_emojis"` // https://pg.uptrace.dev/orm/many-to-many-relation/
|
||||
EmojiIDs []string `bun:"emojis,array"`
|
||||
Emojis []*Emoji `bun:"attached_emojis,m2m:status_to_emojis"` // https://pg.uptrace.dev/orm/many-to-many-relation/
|
||||
// when was this status created?
|
||||
CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
|
||||
CreatedAt time.Time `bun:"type:timestamp,notnull,default:now()"`
|
||||
// when was this status updated?
|
||||
UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
|
||||
UpdatedAt time.Time `bun:"type:timestamp,notnull,default:now()"`
|
||||
// is this status from a local account?
|
||||
Local bool
|
||||
// which account posted this status?
|
||||
AccountID string `pg:"type:CHAR(26),notnull"`
|
||||
Account *Account `pg:"rel:has-one"`
|
||||
AccountID string `bun:"type:CHAR(26),notnull"`
|
||||
Account *Account `bun:"rel:belongs-to"`
|
||||
// AP uri of the owner of this status
|
||||
AccountURI string
|
||||
// id of the status this status is a reply to
|
||||
InReplyToID string `pg:"type:CHAR(26)"`
|
||||
InReplyTo *Status `pg:"rel:has-one"`
|
||||
InReplyToID string `bun:"type:CHAR(26)"`
|
||||
InReplyTo *Status `bun:"rel:belongs-to"`
|
||||
// AP uri of the status this status is a reply to
|
||||
InReplyToURI string
|
||||
// id of the account that this status replies to
|
||||
InReplyToAccountID string `pg:"type:CHAR(26)"`
|
||||
InReplyToAccount *Account `pg:"rel:has-one"`
|
||||
InReplyToAccountID string `bun:"type:CHAR(26)"`
|
||||
InReplyToAccount *Account `bun:"rel:belongs-to"`
|
||||
// id of the status this status is a boost of
|
||||
BoostOfID string `pg:"type:CHAR(26)"`
|
||||
BoostOf *Status `pg:"rel:has-one"`
|
||||
BoostOfID string `bun:"type:CHAR(26)"`
|
||||
BoostOf *Status `bun:"rel:belongs-to"`
|
||||
// id of the account that owns the boosted status
|
||||
BoostOfAccountID string `pg:"type:CHAR(26)"`
|
||||
BoostOfAccount *Account `pg:"rel:has-one"`
|
||||
BoostOfAccountID string `bun:"type:CHAR(26)"`
|
||||
BoostOfAccount *Account `bun:"rel:belongs-to"`
|
||||
// cw string for this status
|
||||
ContentWarning string
|
||||
// visibility entry for this status
|
||||
Visibility Visibility `pg:",notnull"`
|
||||
Visibility Visibility `bun:",notnull"`
|
||||
// mark the status as sensitive?
|
||||
Sensitive bool
|
||||
// what language is this status written in?
|
||||
Language string
|
||||
// Which application was used to create this status?
|
||||
CreatedWithApplicationID string `pg:"type:CHAR(26)"`
|
||||
CreatedWithApplication *Application `pg:"rel:has-one"`
|
||||
CreatedWithApplicationID string `bun:"type:CHAR(26)"`
|
||||
CreatedWithApplication *Application `bun:"rel:belongs-to"`
|
||||
// advanced visibility for this status
|
||||
VisibilityAdvanced *VisibilityAdvanced
|
||||
// What is the activitystreams type of this status? See: https://www.w3.org/TR/activitystreams-vocabulary/#object-types
|
||||
|
|
@ -93,14 +93,18 @@ type Status struct {
|
|||
|
||||
// StatusToTag is an intermediate struct to facilitate the many2many relationship between a status and one or more tags.
|
||||
type StatusToTag struct {
|
||||
StatusID string `pg:"unique:statustag"`
|
||||
TagID string `pg:"unique:statustag"`
|
||||
StatusID string `bun:"type:CHAR(26),unique:statustag"`
|
||||
Status *Status `bun:"rel:has-one"`
|
||||
TagID string `bun:"type:CHAR(26),unique:statustag"`
|
||||
Tag *Tag `bun:"rel:has-one"`
|
||||
}
|
||||
|
||||
// StatusToEmoji is an intermediate struct to facilitate the many2many relationship between a status and one or more emojis.
|
||||
type StatusToEmoji struct {
|
||||
StatusID string `pg:"unique:statusemoji"`
|
||||
EmojiID string `pg:"unique:statusemoji"`
|
||||
StatusID string `bun:"type:CHAR(26),unique:statusemoji"`
|
||||
Status *Status `bun:"rel:has-one"`
|
||||
EmojiID string `bun:"type:CHAR(26),unique:statusemoji"`
|
||||
Emoji *Emoji `bun:"rel:has-one"`
|
||||
}
|
||||
|
||||
// Visibility represents the visibility granularity of a status.
|
||||
|
|
@ -134,11 +138,11 @@ const (
|
|||
// If DIRECT is selected, boostable will be FALSE, and all other flags will be TRUE.
|
||||
type VisibilityAdvanced struct {
|
||||
// This status will be federated beyond the local timeline(s)
|
||||
Federated bool `pg:"default:true"`
|
||||
Federated bool `bun:"default:true"`
|
||||
// This status can be boosted/reblogged
|
||||
Boostable bool `pg:"default:true"`
|
||||
Boostable bool `bun:"default:true"`
|
||||
// This status can be replied to
|
||||
Replyable bool `pg:"default:true"`
|
||||
Replyable bool `bun:"default:true"`
|
||||
// This status can be liked/faved
|
||||
Likeable bool `pg:"default:true"`
|
||||
Likeable bool `bun:"default:true"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,15 +23,15 @@ import "time"
|
|||
// StatusBookmark refers to one account having a 'bookmark' of the status of another account
|
||||
type StatusBookmark struct {
|
||||
// id of this bookmark in the database
|
||||
ID string `pg:"type:CHAR(26),pk,notnull,unique"`
|
||||
ID string `bun:"type:CHAR(26),pk,notnull,unique"`
|
||||
// when was this bookmark created
|
||||
CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
|
||||
CreatedAt time.Time `bun:"type:timestamp,notnull,default:now()"`
|
||||
// id of the account that created ('did') the bookmarking
|
||||
AccountID string `pg:"type:CHAR(26),notnull"`
|
||||
Account *Account `pg:"rel:belongs-to"`
|
||||
AccountID string `bun:"type:CHAR(26),notnull"`
|
||||
Account *Account `bun:"rel:belongs-to"`
|
||||
// id the account owning the bookmarked status
|
||||
TargetAccountID string `pg:"type:CHAR(26),notnull"`
|
||||
TargetAccount *Account `pg:"rel:has-one"`
|
||||
TargetAccountID string `bun:"type:CHAR(26),notnull"`
|
||||
TargetAccount *Account `bun:"rel:belongs-to"`
|
||||
// database id of the status that has been bookmarked
|
||||
StatusID string `pg:"type:CHAR(26),notnull"`
|
||||
StatusID string `bun:"type:CHAR(26),notnull"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,18 +23,18 @@ import "time"
|
|||
// StatusFave refers to a 'fave' or 'like' in the database, from one account, targeting the status of another account
|
||||
type StatusFave struct {
|
||||
// id of this fave in the database
|
||||
ID string `pg:"type:CHAR(26),pk,notnull,unique"`
|
||||
ID string `bun:"type:CHAR(26),pk,notnull,unique"`
|
||||
// when was this fave created
|
||||
CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
|
||||
CreatedAt time.Time `bun:"type:timestamp,notnull,default:now()"`
|
||||
// id of the account that created ('did') the fave
|
||||
AccountID string `pg:"type:CHAR(26),notnull"`
|
||||
Account *Account `pg:"rel:has-one"`
|
||||
AccountID string `bun:"type:CHAR(26),notnull"`
|
||||
Account *Account `bun:"rel:belongs-to"`
|
||||
// id the account owning the faved status
|
||||
TargetAccountID string `pg:"type:CHAR(26),notnull"`
|
||||
TargetAccount *Account `pg:"rel:has-one"`
|
||||
TargetAccountID string `bun:"type:CHAR(26),notnull"`
|
||||
TargetAccount *Account `bun:"rel:belongs-to"`
|
||||
// database id of the status that has been 'faved'
|
||||
StatusID string `pg:"type:CHAR(26),notnull"`
|
||||
Status *Status `pg:"rel:has-one"`
|
||||
StatusID string `bun:"type:CHAR(26),notnull"`
|
||||
Status *Status `bun:"rel:belongs-to"`
|
||||
// ActivityPub URI of this fave
|
||||
URI string `pg:",notnull"`
|
||||
URI string `bun:",notnull"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,16 +23,16 @@ import "time"
|
|||
// StatusMute refers to one account having muted the status of another account or its own
|
||||
type StatusMute struct {
|
||||
// id of this mute in the database
|
||||
ID string `pg:"type:CHAR(26),pk,notnull,unique"`
|
||||
ID string `bun:"type:CHAR(26),pk,notnull,unique"`
|
||||
// when was this mute created
|
||||
CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
|
||||
CreatedAt time.Time `bun:"type:timestamp,notnull,default:now()"`
|
||||
// id of the account that created ('did') the mute
|
||||
AccountID string `pg:"type:CHAR(26),notnull"`
|
||||
Account *Account `pg:"rel:belongs-to"`
|
||||
AccountID string `bun:"type:CHAR(26),notnull"`
|
||||
Account *Account `bun:"rel:belongs-to"`
|
||||
// id the account owning the muted status (can be the same as accountID)
|
||||
TargetAccountID string `pg:"type:CHAR(26),notnull"`
|
||||
TargetAccount *Account `pg:"rel:has-one"`
|
||||
TargetAccountID string `bun:"type:CHAR(26),notnull"`
|
||||
TargetAccount *Account `bun:"rel:belongs-to"`
|
||||
// database id of the status that has been muted
|
||||
StatusID string `pg:"type:CHAR(26),notnull"`
|
||||
Status *Status `pg:"rel:has-one"`
|
||||
StatusID string `bun:"type:CHAR(26),notnull"`
|
||||
Status *Status `bun:"rel:belongs-to"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,21 +23,21 @@ import "time"
|
|||
// Tag represents a hashtag for gathering public statuses together
|
||||
type Tag struct {
|
||||
// id of this tag in the database
|
||||
ID string `pg:",unique,type:CHAR(26),pk,notnull"`
|
||||
ID string `bun:",unique,type:CHAR(26),pk,notnull"`
|
||||
// Href of this tag, eg https://example.org/tags/somehashtag
|
||||
URL string
|
||||
// name of this tag -- the tag without the hash part
|
||||
Name string `pg:",unique,notnull"`
|
||||
Name string `bun:",unique,notnull"`
|
||||
// Which account ID is the first one we saw using this tag?
|
||||
FirstSeenFromAccountID string `pg:"type:CHAR(26)"`
|
||||
FirstSeenFromAccountID string `bun:"type:CHAR(26)"`
|
||||
// when was this tag created
|
||||
CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
|
||||
CreatedAt time.Time `bun:"type:timestamp,notnull,default:now()"`
|
||||
// when was this tag last updated
|
||||
UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
|
||||
UpdatedAt time.Time `bun:"type:timestamp,notnull,default:now()"`
|
||||
// can our instance users use this tag?
|
||||
Useable bool `pg:",notnull,default:true"`
|
||||
Useable bool `bun:",notnull,default:true"`
|
||||
// can our instance users look up this tag?
|
||||
Listable bool `pg:",notnull,default:true"`
|
||||
Listable bool `bun:",notnull,default:true"`
|
||||
// when was this tag last used?
|
||||
LastStatusAt time.Time `pg:"type:timestamp,notnull,default:now()"`
|
||||
LastStatusAt time.Time `bun:"type:timestamp,notnull,default:now()"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,37 +31,37 @@ type User struct {
|
|||
*/
|
||||
|
||||
// id of this user in the local database; the end-user will never need to know this, it's strictly internal
|
||||
ID string `pg:"type:CHAR(26),pk,notnull,unique"`
|
||||
ID string `bun:"type:CHAR(26),pk,notnull,unique"`
|
||||
// confirmed email address for this user, this should be unique -- only one email address registered per instance, multiple users per email are not supported
|
||||
Email string `pg:"default:null,unique"`
|
||||
Email string `bun:"default:null,unique"`
|
||||
// The id of the local gtsmodel.Account entry for this user, if it exists (unconfirmed users don't have an account yet)
|
||||
AccountID string `pg:"type:CHAR(26),unique"`
|
||||
Account *Account `pg:"rel:has-one"`
|
||||
AccountID string `bun:"type:CHAR(26),unique"`
|
||||
Account *Account `bun:"rel:belongs-to"`
|
||||
// The encrypted password of this user, generated using https://pkg.go.dev/golang.org/x/crypto/bcrypt#GenerateFromPassword. A salt is included so we're safe against 🌈 tables
|
||||
EncryptedPassword string `pg:",notnull"`
|
||||
EncryptedPassword string `bun:",notnull"`
|
||||
|
||||
/*
|
||||
USER METADATA
|
||||
*/
|
||||
|
||||
// When was this user created?
|
||||
CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
|
||||
CreatedAt time.Time `bun:"type:timestamp,notnull,default:now()"`
|
||||
// From what IP was this user created?
|
||||
SignUpIP net.IP
|
||||
// When was this user updated (eg., password changed, email address changed)?
|
||||
UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
|
||||
UpdatedAt time.Time `bun:"type:timestamp,notnull,default:now()"`
|
||||
// When did this user sign in for their current session?
|
||||
CurrentSignInAt time.Time `pg:"type:timestamp"`
|
||||
CurrentSignInAt time.Time `bun:"type:timestamp"`
|
||||
// What's the most recent IP of this user
|
||||
CurrentSignInIP net.IP
|
||||
// When did this user last sign in?
|
||||
LastSignInAt time.Time `pg:"type:timestamp"`
|
||||
LastSignInAt time.Time `bun:"type:timestamp"`
|
||||
// What's the previous IP of this user?
|
||||
LastSignInIP net.IP
|
||||
// How many times has this user signed in?
|
||||
SignInCount int
|
||||
// id of the user who invited this user (who let this guy in?)
|
||||
InviteID string `pg:"type:CHAR(26)"`
|
||||
InviteID string `bun:"type:CHAR(26)"`
|
||||
// What languages does this user want to see?
|
||||
ChosenLanguages []string
|
||||
// What languages does this user not want to see?
|
||||
|
|
@ -69,10 +69,10 @@ type User struct {
|
|||
// In what timezone/locale is this user located?
|
||||
Locale string
|
||||
// Which application id created this user? See gtsmodel.Application
|
||||
CreatedByApplicationID string `pg:"type:CHAR(26)"`
|
||||
CreatedByApplication *Application `pg:"rel:has-one"`
|
||||
CreatedByApplicationID string `bun:"type:CHAR(26)"`
|
||||
CreatedByApplication *Application `bun:"rel:belongs-to"`
|
||||
// When did we last contact this user
|
||||
LastEmailedAt time.Time `pg:"type:timestamp"`
|
||||
LastEmailedAt time.Time `bun:"type:timestamp"`
|
||||
|
||||
/*
|
||||
USER CONFIRMATION
|
||||
|
|
@ -81,9 +81,9 @@ type User struct {
|
|||
// What confirmation token did we send this user/what are we expecting back?
|
||||
ConfirmationToken string
|
||||
// When did the user confirm their email address
|
||||
ConfirmedAt time.Time `pg:"type:timestamp"`
|
||||
ConfirmedAt time.Time `bun:"type:timestamp"`
|
||||
// When did we send email confirmation to this user?
|
||||
ConfirmationSentAt time.Time `pg:"type:timestamp"`
|
||||
ConfirmationSentAt time.Time `bun:"type:timestamp"`
|
||||
// Email address that hasn't yet been confirmed
|
||||
UnconfirmedEmail string
|
||||
|
||||
|
|
@ -107,7 +107,7 @@ type User struct {
|
|||
// The generated token that the user can use to reset their password
|
||||
ResetPasswordToken string
|
||||
// When did we email the user their reset-password email?
|
||||
ResetPasswordSentAt time.Time `pg:"type:timestamp"`
|
||||
ResetPasswordSentAt time.Time `bun:"type:timestamp"`
|
||||
|
||||
EncryptedOTPSecret string
|
||||
EncryptedOTPSecretIv string
|
||||
|
|
@ -117,6 +117,6 @@ type User struct {
|
|||
ConsumedTimestamp int
|
||||
RememberToken string
|
||||
SignInToken string
|
||||
SignInTokenSentAt time.Time `pg:"type:timestamp"`
|
||||
SignInTokenSentAt time.Time `bun:"type:timestamp"`
|
||||
WebauthnID string
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ func (p *processor) Get(ctx context.Context, requestingAccount *gtsmodel.Account
|
|||
|
||||
var mastoAccount *apimodel.Account
|
||||
if blocked {
|
||||
mastoAccount, err = p.tc.AccountToMastoBlocked(targetAccount)
|
||||
mastoAccount, err = p.tc.AccountToMastoBlocked(ctx, targetAccount)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error converting account: %s", err)
|
||||
}
|
||||
|
|
@ -57,16 +57,16 @@ func (p *processor) Get(ctx context.Context, requestingAccount *gtsmodel.Account
|
|||
|
||||
// last-minute check to make sure we have remote account header/avi cached
|
||||
if targetAccount.Domain != "" {
|
||||
a, err := p.federator.EnrichRemoteAccount(requestingAccount.Username, targetAccount)
|
||||
a, err := p.federator.EnrichRemoteAccount(ctx, requestingAccount.Username, targetAccount)
|
||||
if err == nil {
|
||||
targetAccount = a
|
||||
}
|
||||
}
|
||||
|
||||
if requestingAccount != nil && targetAccount.ID == requestingAccount.ID {
|
||||
mastoAccount, err = p.tc.AccountToMastoSensitive(targetAccount)
|
||||
mastoAccount, err = p.tc.AccountToMastoSensitive(ctx, targetAccount)
|
||||
} else {
|
||||
mastoAccount, err = p.tc.AccountToMastoPublic(targetAccount)
|
||||
mastoAccount, err = p.tc.AccountToMastoPublic(ctx, targetAccount)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error converting account: %s", err)
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ func (p *processor) FollowersGet(ctx context.Context, requestingAccount *gtsmode
|
|||
f.Account = a
|
||||
}
|
||||
|
||||
account, err := p.tc.AccountToMastoPublic(f.Account)
|
||||
account, err := p.tc.AccountToMastoPublic(ctx, f.Account)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ func (p *processor) FollowingGet(ctx context.Context, requestingAccount *gtsmode
|
|||
f.TargetAccount = a
|
||||
}
|
||||
|
||||
account, err := p.tc.AccountToMastoPublic(f.TargetAccount)
|
||||
account, err := p.tc.AccountToMastoPublic(ctx, f.TargetAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ func (p *processor) RelationshipGet(ctx context.Context, requestingAccount *gtsm
|
|||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("error getting relationship: %s", err))
|
||||
}
|
||||
|
||||
r, err := p.tc.RelationshipToMasto(gtsR)
|
||||
r, err := p.tc.RelationshipToMasto(ctx, gtsR)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting relationship: %s", err))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,12 +46,12 @@ func (p *processor) StatusesGet(ctx context.Context, requestingAccount *gtsmodel
|
|||
}
|
||||
|
||||
for _, s := range statuses {
|
||||
visible, err := p.filter.StatusVisible(s, requestingAccount)
|
||||
visible, err := p.filter.StatusVisible(ctx, s, requestingAccount)
|
||||
if err != nil || !visible {
|
||||
continue
|
||||
}
|
||||
|
||||
apiStatus, err := p.tc.StatusToMasto(s, requestingAccount)
|
||||
apiStatus, err := p.tc.StatusToMasto(ctx, s, requestingAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting status to masto: %s", err))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ func (p *processor) Update(ctx context.Context, account *gtsmodel.Account, form
|
|||
OriginAccount: updatedAccount,
|
||||
}
|
||||
|
||||
acctSensitive, err := p.tc.AccountToMastoSensitive(updatedAccount)
|
||||
acctSensitive, err := p.tc.AccountToMastoSensitive(ctx, updatedAccount)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not convert account into mastosensitive account: %s", err)
|
||||
}
|
||||
|
|
@ -161,7 +161,7 @@ func (p *processor) UpdateAvatar(ctx context.Context, avatar *multipart.FileHead
|
|||
}
|
||||
|
||||
// do the setting
|
||||
avatarInfo, err := p.mediaHandler.ProcessHeaderOrAvatar(buf.Bytes(), accountID, media.Avatar, "")
|
||||
avatarInfo, err := p.mediaHandler.ProcessHeaderOrAvatar(ctx, buf.Bytes(), accountID, media.Avatar, "")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error processing avatar: %s", err)
|
||||
}
|
||||
|
|
@ -194,7 +194,7 @@ func (p *processor) UpdateHeader(ctx context.Context, header *multipart.FileHead
|
|||
}
|
||||
|
||||
// do the setting
|
||||
headerInfo, err := p.mediaHandler.ProcessHeaderOrAvatar(buf.Bytes(), accountID, media.Header, "")
|
||||
headerInfo, err := p.mediaHandler.ProcessHeaderOrAvatar(ctx, buf.Bytes(), accountID, media.Header, "")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error processing header: %s", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ func (p *processor) DomainBlockCreate(ctx context.Context, account *gtsmodel.Acc
|
|||
go p.initiateDomainBlockSideEffects(ctx, account, domainBlock) // TODO: add this to a queuing system so it can retry/resume
|
||||
}
|
||||
|
||||
mastoDomainBlock, err := p.tc.DomainBlockToMasto(domainBlock, false)
|
||||
mastoDomainBlock, err := p.tc.DomainBlockToMasto(ctx, domainBlock, false)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("DomainBlockCreate: error converting domain block to frontend/masto representation %s: %s", domain, err))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ func (p *processor) DomainBlockDelete(ctx context.Context, account *gtsmodel.Acc
|
|||
}
|
||||
|
||||
// prepare the domain block to return
|
||||
mastoDomainBlock, err := p.tc.DomainBlockToMasto(domainBlock, false)
|
||||
mastoDomainBlock, err := p.tc.DomainBlockToMasto(ctx, domainBlock, false)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ func (p *processor) EmojiCreate(ctx context.Context, account *gtsmodel.Account,
|
|||
}
|
||||
|
||||
// allow the mediaHandler to work its magic of processing the emoji bytes, and putting them in whatever storage backend we're using
|
||||
emoji, err := p.mediaHandler.ProcessLocalEmoji(buf.Bytes(), form.Shortcode)
|
||||
emoji, err := p.mediaHandler.ProcessLocalEmoji(ctx, buf.Bytes(), form.Shortcode)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error reading emoji: %s", err)
|
||||
}
|
||||
|
|
@ -61,7 +61,7 @@ func (p *processor) EmojiCreate(ctx context.Context, account *gtsmodel.Account,
|
|||
}
|
||||
emoji.ID = emojiID
|
||||
|
||||
mastoEmoji, err := p.tc.EmojiToMasto(emoji)
|
||||
mastoEmoji, err := p.tc.EmojiToMasto(ctx, emoji)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error converting emoji to mastotype: %s", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ func (p *processor) DomainBlockGet(ctx context.Context, account *gtsmodel.Accoun
|
|||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("no entry for ID %s", id))
|
||||
}
|
||||
|
||||
mastoDomainBlock, err := p.tc.DomainBlockToMasto(domainBlock, export)
|
||||
mastoDomainBlock, err := p.tc.DomainBlockToMasto(ctx, domainBlock, export)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ func (p *processor) DomainBlocksGet(ctx context.Context, account *gtsmodel.Accou
|
|||
|
||||
mastoDomainBlocks := []*apimodel.DomainBlock{}
|
||||
for _, b := range domainBlocks {
|
||||
mastoDomainBlock, err := p.tc.DomainBlockToMasto(b, export)
|
||||
mastoDomainBlock, err := p.tc.DomainBlockToMasto(ctx, b, export)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ func (p *processor) AppCreate(ctx context.Context, authed *oauth.Auth, form *api
|
|||
return nil, err
|
||||
}
|
||||
|
||||
mastoApp, err := p.tc.AppToMastoSensitive(app)
|
||||
mastoApp, err := p.tc.AppToMastoSensitive(ctx, app)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ func (p *processor) BlocksGet(ctx context.Context, authed *oauth.Auth, maxID str
|
|||
|
||||
apiAccounts := []*apimodel.Account{}
|
||||
for _, a := range accounts {
|
||||
apiAccount, err := p.tc.AccountToMastoBlocked(a)
|
||||
apiAccount, err := p.tc.AccountToMastoBlocked(ctx, a)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ func (p *processor) GetFediUser(ctx context.Context, requestedUsername string, r
|
|||
var requestedPerson vocab.ActivityStreamsPerson
|
||||
if util.IsPublicKeyPath(requestURL) {
|
||||
// if it's a public key path, we don't need to authenticate but we'll only serve the bare minimum user profile needed for the public key
|
||||
requestedPerson, err = p.tc.AccountToASMinimal(requestedAccount)
|
||||
requestedPerson, err = p.tc.AccountToASMinimal(ctx, requestedAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
|
@ -56,8 +56,8 @@ func (p *processor) GetFediUser(ctx context.Context, requestedUsername string, r
|
|||
}
|
||||
|
||||
// if we're not already handshaking/dereferencing a remote account, dereference it now
|
||||
if !p.federator.Handshaking(requestedUsername, requestingAccountURI) {
|
||||
requestingAccount, _, err := p.federator.GetRemoteAccount(requestedUsername, requestingAccountURI, false)
|
||||
if !p.federator.Handshaking(ctx, requestedUsername, requestingAccountURI) {
|
||||
requestingAccount, _, err := p.federator.GetRemoteAccount(ctx, requestedUsername, requestingAccountURI, false)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotAuthorized(err)
|
||||
}
|
||||
|
|
@ -72,7 +72,7 @@ func (p *processor) GetFediUser(ctx context.Context, requestedUsername string, r
|
|||
}
|
||||
}
|
||||
|
||||
requestedPerson, err = p.tc.AccountToAS(requestedAccount)
|
||||
requestedPerson, err = p.tc.AccountToAS(ctx, requestedAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
|
@ -101,7 +101,7 @@ func (p *processor) GetFediFollowers(ctx context.Context, requestedUsername stri
|
|||
return nil, gtserror.NewErrorNotAuthorized(errors.New("not authorized"), "not authorized")
|
||||
}
|
||||
|
||||
requestingAccount, _, err := p.federator.GetRemoteAccount(requestedUsername, requestingAccountURI, false)
|
||||
requestingAccount, _, err := p.federator.GetRemoteAccount(ctx, requestedUsername, requestingAccountURI, false)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotAuthorized(err)
|
||||
}
|
||||
|
|
@ -146,7 +146,7 @@ func (p *processor) GetFediFollowing(ctx context.Context, requestedUsername stri
|
|||
return nil, gtserror.NewErrorNotAuthorized(errors.New("not authorized"), "not authorized")
|
||||
}
|
||||
|
||||
requestingAccount, _, err := p.federator.GetRemoteAccount(requestedUsername, requestingAccountURI, false)
|
||||
requestingAccount, _, err := p.federator.GetRemoteAccount(ctx, requestedUsername, requestingAccountURI, false)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotAuthorized(err)
|
||||
}
|
||||
|
|
@ -191,7 +191,7 @@ func (p *processor) GetFediStatus(ctx context.Context, requestedUsername string,
|
|||
return nil, gtserror.NewErrorNotAuthorized(errors.New("not authorized"), "not authorized")
|
||||
}
|
||||
|
||||
requestingAccount, _, err := p.federator.GetRemoteAccount(requestedUsername, requestingAccountURI, false)
|
||||
requestingAccount, _, err := p.federator.GetRemoteAccount(ctx, requestedUsername, requestingAccountURI, false)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotAuthorized(err)
|
||||
}
|
||||
|
|
@ -216,7 +216,7 @@ func (p *processor) GetFediStatus(ctx context.Context, requestedUsername string,
|
|||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("database error getting status with id %s and account id %s: %s", requestedStatusID, requestedAccount.ID, err))
|
||||
}
|
||||
|
||||
visible, err := p.filter.StatusVisible(s, requestingAccount)
|
||||
visible, err := p.filter.StatusVisible(ctx, s, requestingAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
|
@ -225,7 +225,7 @@ func (p *processor) GetFediStatus(ctx context.Context, requestedUsername string,
|
|||
}
|
||||
|
||||
// requester is authorized to view the status, so convert it to AP representation and serialize it
|
||||
asStatus, err := p.tc.StatusToAS(s)
|
||||
asStatus, err := p.tc.StatusToAS(ctx, s)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
|
@ -251,7 +251,7 @@ func (p *processor) GetFediStatusReplies(ctx context.Context, requestedUsername
|
|||
return nil, gtserror.NewErrorNotAuthorized(errors.New("not authorized"), "not authorized")
|
||||
}
|
||||
|
||||
requestingAccount, _, err := p.federator.GetRemoteAccount(requestedUsername, requestingAccountURI, false)
|
||||
requestingAccount, _, err := p.federator.GetRemoteAccount(ctx, requestedUsername, requestingAccountURI, false)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotAuthorized(err)
|
||||
}
|
||||
|
|
@ -276,7 +276,7 @@ func (p *processor) GetFediStatusReplies(ctx context.Context, requestedUsername
|
|||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("database error getting status with id %s and account id %s: %s", requestedStatusID, requestedAccount.ID, err))
|
||||
}
|
||||
|
||||
visible, err := p.filter.StatusVisible(s, requestingAccount)
|
||||
visible, err := p.filter.StatusVisible(ctx, s, requestingAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
|
@ -295,7 +295,7 @@ func (p *processor) GetFediStatusReplies(ctx context.Context, requestedUsername
|
|||
// scenario 1
|
||||
|
||||
// get the collection
|
||||
collection, err := p.tc.StatusToASRepliesCollection(s, onlyOtherAccounts)
|
||||
collection, err := p.tc.StatusToASRepliesCollection(ctx, s, onlyOtherAccounts)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
|
@ -308,7 +308,7 @@ func (p *processor) GetFediStatusReplies(ctx context.Context, requestedUsername
|
|||
// scenario 2
|
||||
|
||||
// get the collection
|
||||
collection, err := p.tc.StatusToASRepliesCollection(s, onlyOtherAccounts)
|
||||
collection, err := p.tc.StatusToASRepliesCollection(ctx, s, onlyOtherAccounts)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
|
@ -339,13 +339,13 @@ func (p *processor) GetFediStatusReplies(ctx context.Context, requestedUsername
|
|||
}
|
||||
|
||||
// only show replies that the status owner can see
|
||||
visibleToStatusOwner, err := p.filter.StatusVisible(r, requestedAccount)
|
||||
visibleToStatusOwner, err := p.filter.StatusVisible(ctx, r, requestedAccount)
|
||||
if err != nil || !visibleToStatusOwner {
|
||||
continue
|
||||
}
|
||||
|
||||
// only show replies that the requester can see
|
||||
visibleToRequester, err := p.filter.StatusVisible(r, requestingAccount)
|
||||
visibleToRequester, err := p.filter.StatusVisible(ctx, r, requestingAccount)
|
||||
if err != nil || !visibleToRequester {
|
||||
continue
|
||||
}
|
||||
|
|
@ -358,7 +358,7 @@ func (p *processor) GetFediStatusReplies(ctx context.Context, requestedUsername
|
|||
replyURIs[r.ID] = rURI
|
||||
}
|
||||
|
||||
repliesPage, err := p.tc.StatusURIsToASRepliesPage(s, onlyOtherAccounts, minID, replyURIs)
|
||||
repliesPage, err := p.tc.StatusURIsToASRepliesPage(ctx, s, onlyOtherAccounts, minID, replyURIs)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ func (p *processor) FollowRequestsGet(ctx context.Context, auth *oauth.Auth) ([]
|
|||
if err := p.db.GetByID(ctx, fr.AccountID, acct); err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
mastoAcct, err := p.tc.AccountToMastoPublic(acct)
|
||||
mastoAcct, err := p.tc.AccountToMastoPublic(ctx, acct)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
|
@ -80,7 +80,7 @@ func (p *processor) FollowRequestAccept(ctx context.Context, auth *oauth.Auth, a
|
|||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
||||
r, err := p.tc.RelationshipToMasto(gtsR)
|
||||
r, err := p.tc.RelationshipToMasto(ctx, gtsR)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -100,10 +100,10 @@ func (p *processor) processFromClientAPI(ctx context.Context, clientMsg gtsmodel
|
|||
}
|
||||
|
||||
// remove any of the blocking account's statuses from the blocked account's timeline, and vice versa
|
||||
if err := p.timelineManager.WipeStatusesFromAccountID(block.AccountID, block.TargetAccountID); err != nil {
|
||||
if err := p.timelineManager.WipeStatusesFromAccountID(ctx, block.AccountID, block.TargetAccountID); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := p.timelineManager.WipeStatusesFromAccountID(block.TargetAccountID, block.AccountID); err != nil {
|
||||
if err := p.timelineManager.WipeStatusesFromAccountID(ctx, block.TargetAccountID, block.AccountID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -171,7 +171,7 @@ func (p *processor) processFromClientAPI(ctx context.Context, clientMsg gtsmodel
|
|||
return errors.New("undo was not parseable as *gtsmodel.Status")
|
||||
}
|
||||
|
||||
if err := p.deleteStatusFromTimelines(boost); err != nil {
|
||||
if err := p.deleteStatusFromTimelines(ctx, boost); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -193,7 +193,7 @@ func (p *processor) processFromClientAPI(ctx context.Context, clientMsg gtsmodel
|
|||
|
||||
// delete all attachments for this status
|
||||
for _, a := range statusToDelete.AttachmentIDs {
|
||||
if err := p.mediaProcessor.Delete(a); err != nil {
|
||||
if err := p.mediaProcessor.Delete(ctx, a); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
@ -211,7 +211,7 @@ func (p *processor) processFromClientAPI(ctx context.Context, clientMsg gtsmodel
|
|||
}
|
||||
|
||||
// delete this status from any and all timelines
|
||||
if err := p.deleteStatusFromTimelines(statusToDelete); err != nil {
|
||||
if err := p.deleteStatusFromTimelines(ctx, statusToDelete); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -250,7 +250,7 @@ func (p *processor) federateStatus(ctx context.Context, status *gtsmodel.Status)
|
|||
return nil
|
||||
}
|
||||
|
||||
asStatus, err := p.tc.StatusToAS(status)
|
||||
asStatus, err := p.tc.StatusToAS(ctx, status)
|
||||
if err != nil {
|
||||
return fmt.Errorf("federateStatus: error converting status to as format: %s", err)
|
||||
}
|
||||
|
|
@ -278,7 +278,7 @@ func (p *processor) federateStatusDelete(ctx context.Context, status *gtsmodel.S
|
|||
return nil
|
||||
}
|
||||
|
||||
asStatus, err := p.tc.StatusToAS(status)
|
||||
asStatus, err := p.tc.StatusToAS(ctx, status)
|
||||
if err != nil {
|
||||
return fmt.Errorf("federateStatusDelete: error converting status to as format: %s", err)
|
||||
}
|
||||
|
|
@ -320,9 +320,9 @@ func (p *processor) federateFollow(ctx context.Context, followRequest *gtsmodel.
|
|||
return nil
|
||||
}
|
||||
|
||||
follow := p.tc.FollowRequestToFollow(followRequest)
|
||||
follow := p.tc.FollowRequestToFollow(ctx, followRequest)
|
||||
|
||||
asFollow, err := p.tc.FollowToAS(follow, originAccount, targetAccount)
|
||||
asFollow, err := p.tc.FollowToAS(ctx, follow, originAccount, targetAccount)
|
||||
if err != nil {
|
||||
return fmt.Errorf("federateFollow: error converting follow to as format: %s", err)
|
||||
}
|
||||
|
|
@ -343,7 +343,7 @@ func (p *processor) federateUnfollow(ctx context.Context, follow *gtsmodel.Follo
|
|||
}
|
||||
|
||||
// recreate the follow
|
||||
asFollow, err := p.tc.FollowToAS(follow, originAccount, targetAccount)
|
||||
asFollow, err := p.tc.FollowToAS(ctx, follow, originAccount, targetAccount)
|
||||
if err != nil {
|
||||
return fmt.Errorf("federateUnfollow: error converting follow to as format: %s", err)
|
||||
}
|
||||
|
|
@ -384,7 +384,7 @@ func (p *processor) federateUnfave(ctx context.Context, fave *gtsmodel.StatusFav
|
|||
}
|
||||
|
||||
// create the AS fave
|
||||
asFave, err := p.tc.FaveToAS(fave)
|
||||
asFave, err := p.tc.FaveToAS(ctx, fave)
|
||||
if err != nil {
|
||||
return fmt.Errorf("federateFave: error converting fave to as format: %s", err)
|
||||
}
|
||||
|
|
@ -422,7 +422,7 @@ func (p *processor) federateUnannounce(ctx context.Context, boost *gtsmodel.Stat
|
|||
return nil
|
||||
}
|
||||
|
||||
asAnnounce, err := p.tc.BoostToAS(boost, originAccount, targetAccount)
|
||||
asAnnounce, err := p.tc.BoostToAS(ctx, boost, originAccount, targetAccount)
|
||||
if err != nil {
|
||||
return fmt.Errorf("federateUnannounce: error converting status to announce: %s", err)
|
||||
}
|
||||
|
|
@ -458,7 +458,7 @@ func (p *processor) federateAcceptFollowRequest(ctx context.Context, follow *gts
|
|||
}
|
||||
|
||||
// recreate the AS follow
|
||||
asFollow, err := p.tc.FollowToAS(follow, originAccount, targetAccount)
|
||||
asFollow, err := p.tc.FollowToAS(ctx, follow, originAccount, targetAccount)
|
||||
if err != nil {
|
||||
return fmt.Errorf("federateUnfollow: error converting follow to as format: %s", err)
|
||||
}
|
||||
|
|
@ -508,7 +508,7 @@ func (p *processor) federateFave(ctx context.Context, fave *gtsmodel.StatusFave,
|
|||
}
|
||||
|
||||
// create the AS fave
|
||||
asFave, err := p.tc.FaveToAS(fave)
|
||||
asFave, err := p.tc.FaveToAS(ctx, fave)
|
||||
if err != nil {
|
||||
return fmt.Errorf("federateFave: error converting fave to as format: %s", err)
|
||||
}
|
||||
|
|
@ -522,7 +522,7 @@ func (p *processor) federateFave(ctx context.Context, fave *gtsmodel.StatusFave,
|
|||
}
|
||||
|
||||
func (p *processor) federateAnnounce(ctx context.Context, boostWrapperStatus *gtsmodel.Status, boostingAccount *gtsmodel.Account, boostedAccount *gtsmodel.Account) error {
|
||||
announce, err := p.tc.BoostToAS(boostWrapperStatus, boostingAccount, boostedAccount)
|
||||
announce, err := p.tc.BoostToAS(ctx, boostWrapperStatus, boostingAccount, boostedAccount)
|
||||
if err != nil {
|
||||
return fmt.Errorf("federateAnnounce: error converting status to announce: %s", err)
|
||||
}
|
||||
|
|
@ -537,7 +537,7 @@ func (p *processor) federateAnnounce(ctx context.Context, boostWrapperStatus *gt
|
|||
}
|
||||
|
||||
func (p *processor) federateAccountUpdate(ctx context.Context, updatedAccount *gtsmodel.Account, originAccount *gtsmodel.Account) error {
|
||||
person, err := p.tc.AccountToAS(updatedAccount)
|
||||
person, err := p.tc.AccountToAS(ctx, updatedAccount)
|
||||
if err != nil {
|
||||
return fmt.Errorf("federateAccountUpdate: error converting account to person: %s", err)
|
||||
}
|
||||
|
|
@ -578,7 +578,7 @@ func (p *processor) federateBlock(ctx context.Context, block *gtsmodel.Block) er
|
|||
return nil
|
||||
}
|
||||
|
||||
asBlock, err := p.tc.BlockToAS(block)
|
||||
asBlock, err := p.tc.BlockToAS(ctx, block)
|
||||
if err != nil {
|
||||
return fmt.Errorf("federateBlock: error converting block to AS format: %s", err)
|
||||
}
|
||||
|
|
@ -614,7 +614,7 @@ func (p *processor) federateUnblock(ctx context.Context, block *gtsmodel.Block)
|
|||
return nil
|
||||
}
|
||||
|
||||
asBlock, err := p.tc.BlockToAS(block)
|
||||
asBlock, err := p.tc.BlockToAS(ctx, block)
|
||||
if err != nil {
|
||||
return fmt.Errorf("federateUnblock: error converting block to AS format: %s", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ func (p *processor) notifyStatus(ctx context.Context, status *gtsmodel.Status) e
|
|||
}
|
||||
|
||||
// now stream the notification to the user
|
||||
mastoNotif, err := p.tc.NotificationToMasto(notif)
|
||||
mastoNotif, err := p.tc.NotificationToMasto(ctx, notif)
|
||||
if err != nil {
|
||||
return fmt.Errorf("notifyStatus: error converting notification to masto representation: %s", err)
|
||||
}
|
||||
|
|
@ -134,7 +134,7 @@ func (p *processor) notifyFollowRequest(ctx context.Context, followRequest *gtsm
|
|||
}
|
||||
|
||||
// now stream the notification to the user
|
||||
mastoNotif, err := p.tc.NotificationToMasto(notif)
|
||||
mastoNotif, err := p.tc.NotificationToMasto(ctx, notif)
|
||||
if err != nil {
|
||||
return fmt.Errorf("notifyStatus: error converting notification to masto representation: %s", err)
|
||||
}
|
||||
|
|
@ -180,7 +180,7 @@ func (p *processor) notifyFollow(ctx context.Context, follow *gtsmodel.Follow, t
|
|||
}
|
||||
|
||||
// now stream the notification to the user
|
||||
mastoNotif, err := p.tc.NotificationToMasto(notif)
|
||||
mastoNotif, err := p.tc.NotificationToMasto(ctx, notif)
|
||||
if err != nil {
|
||||
return fmt.Errorf("notifyStatus: error converting notification to masto representation: %s", err)
|
||||
}
|
||||
|
|
@ -219,7 +219,7 @@ func (p *processor) notifyFave(ctx context.Context, fave *gtsmodel.StatusFave, t
|
|||
}
|
||||
|
||||
// now stream the notification to the user
|
||||
mastoNotif, err := p.tc.NotificationToMasto(notif)
|
||||
mastoNotif, err := p.tc.NotificationToMasto(ctx, notif)
|
||||
if err != nil {
|
||||
return fmt.Errorf("notifyStatus: error converting notification to masto representation: %s", err)
|
||||
}
|
||||
|
|
@ -298,7 +298,7 @@ func (p *processor) notifyAnnounce(ctx context.Context, status *gtsmodel.Status)
|
|||
}
|
||||
|
||||
// now stream the notification to the user
|
||||
mastoNotif, err := p.tc.NotificationToMasto(notif)
|
||||
mastoNotif, err := p.tc.NotificationToMasto(ctx, notif)
|
||||
if err != nil {
|
||||
return fmt.Errorf("notifyStatus: error converting notification to masto representation: %s", err)
|
||||
}
|
||||
|
|
@ -377,7 +377,7 @@ func (p *processor) timelineStatusForAccount(ctx context.Context, status *gtsmod
|
|||
}
|
||||
|
||||
// make sure the status is timelineable
|
||||
timelineable, err := p.filter.StatusHometimelineable(status, timelineAccount)
|
||||
timelineable, err := p.filter.StatusHometimelineable(ctx, status, timelineAccount)
|
||||
if err != nil {
|
||||
errors <- fmt.Errorf("timelineStatusForAccount: error getting timelineability for status for timeline with id %s: %s", accountID, err)
|
||||
return
|
||||
|
|
@ -388,7 +388,7 @@ func (p *processor) timelineStatusForAccount(ctx context.Context, status *gtsmod
|
|||
}
|
||||
|
||||
// stick the status in the timeline for the account and then immediately prepare it so they can see it right away
|
||||
inserted, err := p.timelineManager.IngestAndPrepare(status, timelineAccount.ID)
|
||||
inserted, err := p.timelineManager.IngestAndPrepare(ctx, status, timelineAccount.ID)
|
||||
if err != nil {
|
||||
errors <- fmt.Errorf("timelineStatusForAccount: error ingesting status %s: %s", status.ID, err)
|
||||
return
|
||||
|
|
@ -396,7 +396,7 @@ func (p *processor) timelineStatusForAccount(ctx context.Context, status *gtsmod
|
|||
|
||||
// the status was inserted to stream it to the user
|
||||
if inserted {
|
||||
mastoStatus, err := p.tc.StatusToMasto(status, timelineAccount)
|
||||
mastoStatus, err := p.tc.StatusToMasto(ctx, status, timelineAccount)
|
||||
if err != nil {
|
||||
errors <- fmt.Errorf("timelineStatusForAccount: error converting status %s to frontend representation: %s", status.ID, err)
|
||||
} else {
|
||||
|
|
@ -406,7 +406,7 @@ func (p *processor) timelineStatusForAccount(ctx context.Context, status *gtsmod
|
|||
}
|
||||
}
|
||||
|
||||
mastoStatus, err := p.tc.StatusToMasto(status, timelineAccount)
|
||||
mastoStatus, err := p.tc.StatusToMasto(ctx, status, timelineAccount)
|
||||
if err != nil {
|
||||
errors <- fmt.Errorf("timelineStatusForAccount: error converting status %s to frontend representation: %s", status.ID, err)
|
||||
} else {
|
||||
|
|
@ -416,8 +416,8 @@ func (p *processor) timelineStatusForAccount(ctx context.Context, status *gtsmod
|
|||
}
|
||||
}
|
||||
|
||||
func (p *processor) deleteStatusFromTimelines(status *gtsmodel.Status) error {
|
||||
if err := p.timelineManager.WipeStatusFromAllTimelines(status.ID); err != nil {
|
||||
func (p *processor) deleteStatusFromTimelines(ctx context.Context, status *gtsmodel.Status) error {
|
||||
if err := p.timelineManager.WipeStatusFromAllTimelines(ctx, status.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ func (p *processor) processFromFederator(ctx context.Context, federatorMsg gtsmo
|
|||
return errors.New("note was not parseable as *gtsmodel.Status")
|
||||
}
|
||||
|
||||
status, err := p.federator.EnrichRemoteStatus(federatorMsg.ReceivingAccount.Username, incomingStatus)
|
||||
status, err := p.federator.EnrichRemoteStatus(ctx, federatorMsg.ReceivingAccount.Username, incomingStatus)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -91,7 +91,7 @@ func (p *processor) processFromFederator(ctx context.Context, federatorMsg gtsmo
|
|||
return errors.New("announce was not parseable as *gtsmodel.Status")
|
||||
}
|
||||
|
||||
if err := p.federator.DereferenceAnnounce(incomingAnnounce, federatorMsg.ReceivingAccount.Username); err != nil {
|
||||
if err := p.federator.DereferenceAnnounce(ctx, incomingAnnounce, federatorMsg.ReceivingAccount.Username); err != nil {
|
||||
return fmt.Errorf("error dereferencing announce from federator: %s", err)
|
||||
}
|
||||
|
||||
|
|
@ -122,10 +122,10 @@ func (p *processor) processFromFederator(ctx context.Context, federatorMsg gtsmo
|
|||
}
|
||||
|
||||
// remove any of the blocking account's statuses from the blocked account's timeline, and vice versa
|
||||
if err := p.timelineManager.WipeStatusesFromAccountID(block.AccountID, block.TargetAccountID); err != nil {
|
||||
if err := p.timelineManager.WipeStatusesFromAccountID(ctx, block.AccountID, block.TargetAccountID); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := p.timelineManager.WipeStatusesFromAccountID(block.TargetAccountID, block.AccountID); err != nil {
|
||||
if err := p.timelineManager.WipeStatusesFromAccountID(ctx, block.TargetAccountID, block.AccountID); err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO: same with notifications
|
||||
|
|
@ -146,7 +146,7 @@ func (p *processor) processFromFederator(ctx context.Context, federatorMsg gtsmo
|
|||
return err
|
||||
}
|
||||
|
||||
if _, _, err := p.federator.GetRemoteAccount(federatorMsg.ReceivingAccount.Username, incomingAccountURI, true); err != nil {
|
||||
if _, _, err := p.federator.GetRemoteAccount(ctx, federatorMsg.ReceivingAccount.Username, incomingAccountURI, true); err != nil {
|
||||
return fmt.Errorf("error dereferencing account from federator: %s", err)
|
||||
}
|
||||
}
|
||||
|
|
@ -166,7 +166,7 @@ func (p *processor) processFromFederator(ctx context.Context, federatorMsg gtsmo
|
|||
|
||||
// delete all attachments for this status
|
||||
for _, a := range statusToDelete.AttachmentIDs {
|
||||
if err := p.mediaProcessor.Delete(a); err != nil {
|
||||
if err := p.mediaProcessor.Delete(ctx, a); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
@ -184,7 +184,7 @@ func (p *processor) processFromFederator(ctx context.Context, federatorMsg gtsmo
|
|||
}
|
||||
|
||||
// remove this status from any and all timelines
|
||||
return p.deleteStatusFromTimelines(statusToDelete)
|
||||
return p.deleteStatusFromTimelines(ctx, statusToDelete)
|
||||
case gtsmodel.ActivityStreamsProfile:
|
||||
// DELETE A PROFILE/ACCOUNT
|
||||
// TODO: handle side effects of account deletion here: delete all objects, statuses, media etc associated with account
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ func (p *processor) InstanceGet(ctx context.Context, domain string) (*apimodel.I
|
|||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("db error fetching instance %s: %s", p.config.Host, err))
|
||||
}
|
||||
|
||||
ai, err := p.tc.InstanceToMasto(i)
|
||||
ai, err := p.tc.InstanceToMasto(ctx, i)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting instance to api representation: %s", err))
|
||||
}
|
||||
|
|
@ -151,7 +151,7 @@ func (p *processor) InstancePatch(ctx context.Context, form *apimodel.InstanceSe
|
|||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("db error updating instance %s: %s", p.config.Host, err))
|
||||
}
|
||||
|
||||
ai, err := p.tc.InstanceToMasto(i)
|
||||
ai, err := p.tc.InstanceToMasto(ctx, i)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting instance to api representation: %s", err))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ package media
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
|
@ -29,7 +30,7 @@ import (
|
|||
"github.com/superseriousbusiness/gotosocial/internal/text"
|
||||
)
|
||||
|
||||
func (p *processor) Create(account *gtsmodel.Account, form *apimodel.AttachmentRequest) (*apimodel.Attachment, error) {
|
||||
func (p *processor) Create(ctx context.Context, account *gtsmodel.Account, form *apimodel.AttachmentRequest) (*apimodel.Attachment, error) {
|
||||
// open the attachment and extract the bytes from it
|
||||
f, err := form.File.Open()
|
||||
if err != nil {
|
||||
|
|
@ -45,7 +46,7 @@ func (p *processor) Create(account *gtsmodel.Account, form *apimodel.AttachmentR
|
|||
}
|
||||
|
||||
// allow the mediaHandler to work its magic of processing the attachment bytes, and putting them in whatever storage backend we're using
|
||||
attachment, err := p.mediaHandler.ProcessAttachment(buf.Bytes(), account.ID, "")
|
||||
attachment, err := p.mediaHandler.ProcessAttachment(ctx, buf.Bytes(), account.ID, "")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error reading attachment: %s", err)
|
||||
}
|
||||
|
|
@ -66,13 +67,13 @@ func (p *processor) Create(account *gtsmodel.Account, form *apimodel.AttachmentR
|
|||
|
||||
// prepare the frontend representation now -- if there are any errors here at least we can bail without
|
||||
// having already put something in the database and then having to clean it up again (eugh)
|
||||
mastoAttachment, err := p.tc.AttachmentToMasto(attachment)
|
||||
mastoAttachment, err := p.tc.AttachmentToMasto(ctx, attachment)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error parsing media attachment to frontend type: %s", err)
|
||||
}
|
||||
|
||||
// now we can confidently put the attachment in the database
|
||||
if err := p.db.Put(attachment); err != nil {
|
||||
if err := p.db.Put(ctx, attachment); err != nil {
|
||||
return nil, fmt.Errorf("error storing media attachment in db: %s", err)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package media
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
|
|
@ -9,9 +10,9 @@ import (
|
|||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
)
|
||||
|
||||
func (p *processor) Delete(mediaAttachmentID string) gtserror.WithCode {
|
||||
func (p *processor) Delete(ctx context.Context, mediaAttachmentID string) gtserror.WithCode {
|
||||
a := >smodel.MediaAttachment{}
|
||||
if err := p.db.GetByID(mediaAttachmentID, a); err != nil {
|
||||
if err := p.db.GetByID(ctx, mediaAttachmentID, a); err != nil {
|
||||
if err == db.ErrNoEntries {
|
||||
// attachment already gone
|
||||
return nil
|
||||
|
|
@ -37,7 +38,7 @@ func (p *processor) Delete(mediaAttachmentID string) gtserror.WithCode {
|
|||
}
|
||||
|
||||
// delete the attachment
|
||||
if err := p.db.DeleteByID(mediaAttachmentID, a); err != nil {
|
||||
if err := p.db.DeleteByID(ctx, mediaAttachmentID, a); err != nil {
|
||||
if err != db.ErrNoEntries {
|
||||
errs = append(errs, fmt.Sprintf("remove attachment: %s", err))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
package media
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
|
|
@ -28,7 +29,7 @@ import (
|
|||
"github.com/superseriousbusiness/gotosocial/internal/media"
|
||||
)
|
||||
|
||||
func (p *processor) GetFile(account *gtsmodel.Account, form *apimodel.GetContentRequestForm) (*apimodel.Content, error) {
|
||||
func (p *processor) GetFile(ctx context.Context, account *gtsmodel.Account, form *apimodel.GetContentRequestForm) (*apimodel.Content, error) {
|
||||
// parse the form fields
|
||||
mediaSize, err := media.ParseMediaSize(form.MediaSize)
|
||||
if err != nil {
|
||||
|
|
@ -48,7 +49,7 @@ func (p *processor) GetFile(account *gtsmodel.Account, form *apimodel.GetContent
|
|||
|
||||
// get the account that owns the media and make sure it's not suspended
|
||||
acct := >smodel.Account{}
|
||||
if err := p.db.GetByID(form.AccountID, acct); err != nil {
|
||||
if err := p.db.GetByID(ctx, form.AccountID, acct); err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("account with id %s could not be selected from the db: %s", form.AccountID, err))
|
||||
}
|
||||
if !acct.SuspendedAt.IsZero() {
|
||||
|
|
@ -57,7 +58,7 @@ func (p *processor) GetFile(account *gtsmodel.Account, form *apimodel.GetContent
|
|||
|
||||
// make sure the requesting account and the media account don't block each other
|
||||
if account != nil {
|
||||
blocked, err := p.db.IsBlocked(account.ID, form.AccountID, true)
|
||||
blocked, err := p.db.IsBlocked(ctx, account.ID, form.AccountID, true)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("block status could not be established between accounts %s and %s: %s", form.AccountID, account.ID, err))
|
||||
}
|
||||
|
|
@ -73,7 +74,7 @@ func (p *processor) GetFile(account *gtsmodel.Account, form *apimodel.GetContent
|
|||
switch mediaType {
|
||||
case media.Emoji:
|
||||
e := >smodel.Emoji{}
|
||||
if err := p.db.GetByID(wantedMediaID, e); err != nil {
|
||||
if err := p.db.GetByID(ctx, wantedMediaID, e); err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("emoji %s could not be taken from the db: %s", wantedMediaID, err))
|
||||
}
|
||||
if e.Disabled {
|
||||
|
|
@ -91,7 +92,7 @@ func (p *processor) GetFile(account *gtsmodel.Account, form *apimodel.GetContent
|
|||
}
|
||||
case media.Attachment, media.Header, media.Avatar:
|
||||
a := >smodel.MediaAttachment{}
|
||||
if err := p.db.GetByID(wantedMediaID, a); err != nil {
|
||||
if err := p.db.GetByID(ctx, wantedMediaID, a); err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("attachment %s could not be taken from the db: %s", wantedMediaID, err))
|
||||
}
|
||||
if a.AccountID != form.AccountID {
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
package media
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
|
|
@ -28,9 +29,9 @@ import (
|
|||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
)
|
||||
|
||||
func (p *processor) GetMedia(account *gtsmodel.Account, mediaAttachmentID string) (*apimodel.Attachment, gtserror.WithCode) {
|
||||
func (p *processor) GetMedia(ctx context.Context, account *gtsmodel.Account, mediaAttachmentID string) (*apimodel.Attachment, gtserror.WithCode) {
|
||||
attachment := >smodel.MediaAttachment{}
|
||||
if err := p.db.GetByID(mediaAttachmentID, attachment); err != nil {
|
||||
if err := p.db.GetByID(ctx, mediaAttachmentID, attachment); err != nil {
|
||||
if err == db.ErrNoEntries {
|
||||
// attachment doesn't exist
|
||||
return nil, gtserror.NewErrorNotFound(errors.New("attachment doesn't exist in the db"))
|
||||
|
|
@ -42,7 +43,7 @@ func (p *processor) GetMedia(account *gtsmodel.Account, mediaAttachmentID string
|
|||
return nil, gtserror.NewErrorNotFound(errors.New("attachment not owned by requesting account"))
|
||||
}
|
||||
|
||||
a, err := p.tc.AttachmentToMasto(attachment)
|
||||
a, err := p.tc.AttachmentToMasto(ctx, attachment)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error converting attachment: %s", err))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@
|
|||
package media
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/blob"
|
||||
|
|
@ -33,12 +35,12 @@ import (
|
|||
// Processor wraps a bunch of functions for processing media actions.
|
||||
type Processor interface {
|
||||
// Create creates a new media attachment belonging to the given account, using the request form.
|
||||
Create(account *gtsmodel.Account, form *apimodel.AttachmentRequest) (*apimodel.Attachment, error)
|
||||
Create(ctx context.Context, account *gtsmodel.Account, form *apimodel.AttachmentRequest) (*apimodel.Attachment, error)
|
||||
// Delete deletes the media attachment with the given ID, including all files pertaining to that attachment.
|
||||
Delete(mediaAttachmentID string) gtserror.WithCode
|
||||
GetFile(account *gtsmodel.Account, form *apimodel.GetContentRequestForm) (*apimodel.Content, error)
|
||||
GetMedia(account *gtsmodel.Account, mediaAttachmentID string) (*apimodel.Attachment, gtserror.WithCode)
|
||||
Update(account *gtsmodel.Account, mediaAttachmentID string, form *apimodel.AttachmentUpdateRequest) (*apimodel.Attachment, gtserror.WithCode)
|
||||
Delete(ctx context.Context, mediaAttachmentID string) gtserror.WithCode
|
||||
GetFile(ctx context.Context, account *gtsmodel.Account, form *apimodel.GetContentRequestForm) (*apimodel.Content, error)
|
||||
GetMedia(ctx context.Context, account *gtsmodel.Account, mediaAttachmentID string) (*apimodel.Attachment, gtserror.WithCode)
|
||||
Update(ctx context.Context, account *gtsmodel.Account, mediaAttachmentID string, form *apimodel.AttachmentUpdateRequest) (*apimodel.Attachment, gtserror.WithCode)
|
||||
}
|
||||
|
||||
type processor struct {
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
package media
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
|
|
@ -29,9 +30,9 @@ import (
|
|||
"github.com/superseriousbusiness/gotosocial/internal/text"
|
||||
)
|
||||
|
||||
func (p *processor) Update(account *gtsmodel.Account, mediaAttachmentID string, form *apimodel.AttachmentUpdateRequest) (*apimodel.Attachment, gtserror.WithCode) {
|
||||
func (p *processor) Update(ctx context.Context, account *gtsmodel.Account, mediaAttachmentID string, form *apimodel.AttachmentUpdateRequest) (*apimodel.Attachment, gtserror.WithCode) {
|
||||
attachment := >smodel.MediaAttachment{}
|
||||
if err := p.db.GetByID(mediaAttachmentID, attachment); err != nil {
|
||||
if err := p.db.GetByID(ctx, mediaAttachmentID, attachment); err != nil {
|
||||
if err == db.ErrNoEntries {
|
||||
// attachment doesn't exist
|
||||
return nil, gtserror.NewErrorNotFound(errors.New("attachment doesn't exist in the db"))
|
||||
|
|
@ -45,7 +46,7 @@ func (p *processor) Update(account *gtsmodel.Account, mediaAttachmentID string,
|
|||
|
||||
if form.Description != nil {
|
||||
attachment.Description = text.RemoveHTML(*form.Description)
|
||||
if err := p.db.UpdateByID(mediaAttachmentID, attachment); err != nil {
|
||||
if err := p.db.UpdateByID(ctx, mediaAttachmentID, attachment); err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("database error updating description: %s", err))
|
||||
}
|
||||
}
|
||||
|
|
@ -57,12 +58,12 @@ func (p *processor) Update(account *gtsmodel.Account, mediaAttachmentID string,
|
|||
}
|
||||
attachment.FileMeta.Focus.X = focusx
|
||||
attachment.FileMeta.Focus.Y = focusy
|
||||
if err := p.db.UpdateByID(mediaAttachmentID, attachment); err != nil {
|
||||
if err := p.db.UpdateByID(ctx, mediaAttachmentID, attachment); err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("database error updating focus: %s", err))
|
||||
}
|
||||
}
|
||||
|
||||
a, err := p.tc.AttachmentToMasto(attachment)
|
||||
a, err := p.tc.AttachmentToMasto(ctx, attachment)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error converting attachment: %s", err))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,22 +19,24 @@
|
|||
package processing
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/oauth"
|
||||
)
|
||||
|
||||
func (p *processor) NotificationsGet(authed *oauth.Auth, limit int, maxID string, sinceID string) ([]*apimodel.Notification, gtserror.WithCode) {
|
||||
func (p *processor) NotificationsGet(ctx context.Context, authed *oauth.Auth, limit int, maxID string, sinceID string) ([]*apimodel.Notification, gtserror.WithCode) {
|
||||
l := p.log.WithField("func", "NotificationsGet")
|
||||
|
||||
notifs, err := p.db.GetNotifications(authed.Account.ID, limit, maxID, sinceID)
|
||||
notifs, err := p.db.GetNotifications(ctx, authed.Account.ID, limit, maxID, sinceID)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
||||
mastoNotifs := []*apimodel.Notification{}
|
||||
for _, n := range notifs {
|
||||
mastoNotif, err := p.tc.NotificationToMasto(n)
|
||||
mastoNotif, err := p.tc.NotificationToMasto(ctx, n)
|
||||
if err != nil {
|
||||
l.Debugf("got an error converting a notification to masto, will skip it: %s", err)
|
||||
continue
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ import (
|
|||
// for clean distribution of messages without slowing down the client API and harming the user experience.
|
||||
type Processor interface {
|
||||
// Start starts the Processor, reading from its channels and passing messages back and forth.
|
||||
Start() error
|
||||
Start(ctx context.Context) error
|
||||
// Stop stops the processor cleanly, finishing handling any remaining messages before closing down.
|
||||
Stop() error
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
package processing
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
|
@ -32,7 +33,7 @@ import (
|
|||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
||||
)
|
||||
|
||||
func (p *processor) SearchGet(authed *oauth.Auth, searchQuery *apimodel.SearchQuery) (*apimodel.SearchResult, gtserror.WithCode) {
|
||||
func (p *processor) SearchGet(ctx context.Context, authed *oauth.Auth, searchQuery *apimodel.SearchQuery) (*apimodel.SearchResult, gtserror.WithCode) {
|
||||
l := p.log.WithFields(logrus.Fields{
|
||||
"func": "SearchGet",
|
||||
"query": searchQuery.Query,
|
||||
|
|
@ -54,7 +55,7 @@ func (p *processor) SearchGet(authed *oauth.Auth, searchQuery *apimodel.SearchQu
|
|||
// check if the query is something like @whatever_username@example.org -- this means it's a remote account
|
||||
if !foundOne && util.IsMention(searchQuery.Query) {
|
||||
l.Debug("search term is a mention, looking it up...")
|
||||
foundAccount, err := p.searchAccountByMention(authed, searchQuery.Query, searchQuery.Resolve)
|
||||
foundAccount, err := p.searchAccountByMention(ctx, authed, searchQuery.Query, searchQuery.Resolve)
|
||||
if err == nil && foundAccount != nil {
|
||||
foundAccounts = append(foundAccounts, foundAccount)
|
||||
foundOne = true
|
||||
|
|
@ -65,14 +66,14 @@ func (p *processor) SearchGet(authed *oauth.Auth, searchQuery *apimodel.SearchQu
|
|||
// check if the query is a URI and just do a lookup for that, straight up
|
||||
if uri, err := url.Parse(query); err == nil && !foundOne {
|
||||
// 1. check if it's a status
|
||||
if foundStatus, err := p.searchStatusByURI(authed, uri, searchQuery.Resolve); err == nil && foundStatus != nil {
|
||||
if foundStatus, err := p.searchStatusByURI(ctx, authed, uri, searchQuery.Resolve); err == nil && foundStatus != nil {
|
||||
foundStatuses = append(foundStatuses, foundStatus)
|
||||
foundOne = true
|
||||
l.Debug("got a status by searching by URI")
|
||||
}
|
||||
|
||||
// 2. check if it's an account
|
||||
if foundAccount, err := p.searchAccountByURI(authed, uri, searchQuery.Resolve); err == nil && foundAccount != nil {
|
||||
if foundAccount, err := p.searchAccountByURI(ctx, authed, uri, searchQuery.Resolve); err == nil && foundAccount != nil {
|
||||
foundAccounts = append(foundAccounts, foundAccount)
|
||||
foundOne = true
|
||||
l.Debug("got an account by searching by URI")
|
||||
|
|
@ -90,20 +91,20 @@ func (p *processor) SearchGet(authed *oauth.Auth, searchQuery *apimodel.SearchQu
|
|||
*/
|
||||
for _, foundAccount := range foundAccounts {
|
||||
// make sure there's no block in either direction between the account and the requester
|
||||
if blocked, err := p.db.IsBlocked(authed.Account.ID, foundAccount.ID, true); err == nil && !blocked {
|
||||
if blocked, err := p.db.IsBlocked(ctx, authed.Account.ID, foundAccount.ID, true); err == nil && !blocked {
|
||||
// all good, convert it and add it to the results
|
||||
if acctMasto, err := p.tc.AccountToMastoPublic(foundAccount); err == nil && acctMasto != nil {
|
||||
if acctMasto, err := p.tc.AccountToMastoPublic(ctx, foundAccount); err == nil && acctMasto != nil {
|
||||
results.Accounts = append(results.Accounts, *acctMasto)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, foundStatus := range foundStatuses {
|
||||
if visible, err := p.filter.StatusVisible(foundStatus, authed.Account); !visible || err != nil {
|
||||
if visible, err := p.filter.StatusVisible(ctx, foundStatus, authed.Account); !visible || err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
statusMasto, err := p.tc.StatusToMasto(foundStatus, authed.Account)
|
||||
statusMasto, err := p.tc.StatusToMasto(ctx, foundStatus, authed.Account)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
|
@ -114,24 +115,24 @@ func (p *processor) SearchGet(authed *oauth.Auth, searchQuery *apimodel.SearchQu
|
|||
return results, nil
|
||||
}
|
||||
|
||||
func (p *processor) searchStatusByURI(authed *oauth.Auth, uri *url.URL, resolve bool) (*gtsmodel.Status, error) {
|
||||
func (p *processor) searchStatusByURI(ctx context.Context, authed *oauth.Auth, uri *url.URL, resolve bool) (*gtsmodel.Status, error) {
|
||||
l := p.log.WithFields(logrus.Fields{
|
||||
"func": "searchStatusByURI",
|
||||
"uri": uri.String(),
|
||||
"resolve": resolve,
|
||||
})
|
||||
|
||||
if maybeStatus, err := p.db.GetStatusByURI(uri.String()); err == nil {
|
||||
if maybeStatus, err := p.db.GetStatusByURI(ctx, uri.String()); err == nil {
|
||||
return maybeStatus, nil
|
||||
} else if maybeStatus, err := p.db.GetStatusByURL(uri.String()); err == nil {
|
||||
} else if maybeStatus, err := p.db.GetStatusByURL(ctx, uri.String()); err == nil {
|
||||
return maybeStatus, nil
|
||||
}
|
||||
|
||||
// we don't have it locally so dereference it if we're allowed to
|
||||
if resolve {
|
||||
status, _, _, err := p.federator.GetRemoteStatus(authed.Account.Username, uri, true)
|
||||
status, _, _, err := p.federator.GetRemoteStatus(ctx, authed.Account.Username, uri, true)
|
||||
if err == nil {
|
||||
if err := p.federator.DereferenceRemoteThread(authed.Account.Username, uri); err != nil {
|
||||
if err := p.federator.DereferenceRemoteThread(ctx, authed.Account.Username, uri); err != nil {
|
||||
// try to deref the thread while we're here
|
||||
l.Debugf("searchStatusByURI: error dereferencing remote thread: %s", err)
|
||||
}
|
||||
|
|
@ -141,16 +142,16 @@ func (p *processor) searchStatusByURI(authed *oauth.Auth, uri *url.URL, resolve
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func (p *processor) searchAccountByURI(authed *oauth.Auth, uri *url.URL, resolve bool) (*gtsmodel.Account, error) {
|
||||
if maybeAccount, err := p.db.GetAccountByURI(uri.String()); err == nil {
|
||||
func (p *processor) searchAccountByURI(ctx context.Context, authed *oauth.Auth, uri *url.URL, resolve bool) (*gtsmodel.Account, error) {
|
||||
if maybeAccount, err := p.db.GetAccountByURI(ctx, uri.String()); err == nil {
|
||||
return maybeAccount, nil
|
||||
} else if maybeAccount, err := p.db.GetAccountByURL(uri.String()); err == nil {
|
||||
} else if maybeAccount, err := p.db.GetAccountByURL(ctx, uri.String()); err == nil {
|
||||
return maybeAccount, nil
|
||||
}
|
||||
|
||||
if resolve {
|
||||
// we don't have it locally so try and dereference it
|
||||
account, _, err := p.federator.GetRemoteAccount(authed.Account.Username, uri, true)
|
||||
account, _, err := p.federator.GetRemoteAccount(ctx, authed.Account.Username, uri, true)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("searchAccountByURI: error dereferencing account with uri %s: %s", uri.String(), err)
|
||||
}
|
||||
|
|
@ -159,7 +160,7 @@ func (p *processor) searchAccountByURI(authed *oauth.Auth, uri *url.URL, resolve
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func (p *processor) searchAccountByMention(authed *oauth.Auth, mention string, resolve bool) (*gtsmodel.Account, error) {
|
||||
func (p *processor) searchAccountByMention(ctx context.Context, authed *oauth.Auth, mention string, resolve bool) (*gtsmodel.Account, error) {
|
||||
// query is for a remote account
|
||||
username, domain, err := util.ExtractMentionParts(mention)
|
||||
if err != nil {
|
||||
|
|
@ -169,7 +170,7 @@ func (p *processor) searchAccountByMention(authed *oauth.Auth, mention string, r
|
|||
// if it's a local account we can skip a whole bunch of stuff
|
||||
maybeAcct := >smodel.Account{}
|
||||
if domain == p.config.Host {
|
||||
maybeAcct, err = p.db.GetLocalAccountByUsername(username)
|
||||
maybeAcct, err = p.db.GetLocalAccountByUsername(ctx, username)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("searchAccountByMention: error getting local account by username: %s", err)
|
||||
}
|
||||
|
|
@ -181,7 +182,7 @@ func (p *processor) searchAccountByMention(authed *oauth.Auth, mention string, r
|
|||
{Key: "username", Value: username, CaseInsensitive: true},
|
||||
{Key: "domain", Value: domain, CaseInsensitive: true},
|
||||
}
|
||||
err = p.db.GetWhere(where, maybeAcct)
|
||||
err = p.db.GetWhere(ctx, where, maybeAcct)
|
||||
if err == nil {
|
||||
// we've got it stored locally already!
|
||||
return maybeAcct, nil
|
||||
|
|
@ -197,14 +198,14 @@ func (p *processor) searchAccountByMention(authed *oauth.Auth, mention string, r
|
|||
// we're allowed to resolve it so let's try
|
||||
|
||||
// first we need to webfinger the remote account to convert the username and domain into the activitypub URI for the account
|
||||
acctURI, err := p.federator.FingerRemoteAccount(authed.Account.Username, username, domain)
|
||||
acctURI, err := p.federator.FingerRemoteAccount(ctx, authed.Account.Username, username, domain)
|
||||
if err != nil {
|
||||
// something went wrong doing the webfinger lookup so we can't process the request
|
||||
return nil, fmt.Errorf("searchAccountByMention: error fingering remote account with username %s and domain %s: %s", username, domain, err)
|
||||
}
|
||||
|
||||
// we don't have it locally so try and dereference it
|
||||
account, _, err := p.federator.GetRemoteAccount(authed.Account.Username, acctURI, true)
|
||||
account, _, err := p.federator.GetRemoteAccount(ctx, authed.Account.Username, acctURI, true)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("searchAccountByMention: error dereferencing account with uri %s: %s", acctURI.String(), err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,47 +19,49 @@
|
|||
package processing
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/oauth"
|
||||
)
|
||||
|
||||
func (p *processor) StatusCreate(authed *oauth.Auth, form *apimodel.AdvancedStatusCreateForm) (*apimodel.Status, error) {
|
||||
return p.statusProcessor.Create(authed.Account, authed.Application, form)
|
||||
func (p *processor) StatusCreate(ctx context.Context, authed *oauth.Auth, form *apimodel.AdvancedStatusCreateForm) (*apimodel.Status, error) {
|
||||
return p.statusProcessor.Create(ctx, authed.Account, authed.Application, form)
|
||||
}
|
||||
|
||||
func (p *processor) StatusDelete(authed *oauth.Auth, targetStatusID string) (*apimodel.Status, error) {
|
||||
return p.statusProcessor.Delete(authed.Account, targetStatusID)
|
||||
func (p *processor) StatusDelete(ctx context.Context, authed *oauth.Auth, targetStatusID string) (*apimodel.Status, error) {
|
||||
return p.statusProcessor.Delete(ctx, authed.Account, targetStatusID)
|
||||
}
|
||||
|
||||
func (p *processor) StatusFave(authed *oauth.Auth, targetStatusID string) (*apimodel.Status, error) {
|
||||
return p.statusProcessor.Fave(authed.Account, targetStatusID)
|
||||
func (p *processor) StatusFave(ctx context.Context, authed *oauth.Auth, targetStatusID string) (*apimodel.Status, error) {
|
||||
return p.statusProcessor.Fave(ctx, authed.Account, targetStatusID)
|
||||
}
|
||||
|
||||
func (p *processor) StatusBoost(authed *oauth.Auth, targetStatusID string) (*apimodel.Status, gtserror.WithCode) {
|
||||
return p.statusProcessor.Boost(authed.Account, authed.Application, targetStatusID)
|
||||
func (p *processor) StatusBoost(ctx context.Context, authed *oauth.Auth, targetStatusID string) (*apimodel.Status, gtserror.WithCode) {
|
||||
return p.statusProcessor.Boost(ctx, authed.Account, authed.Application, targetStatusID)
|
||||
}
|
||||
|
||||
func (p *processor) StatusUnboost(authed *oauth.Auth, targetStatusID string) (*apimodel.Status, gtserror.WithCode) {
|
||||
return p.statusProcessor.Unboost(authed.Account, authed.Application, targetStatusID)
|
||||
func (p *processor) StatusUnboost(ctx context.Context, authed *oauth.Auth, targetStatusID string) (*apimodel.Status, gtserror.WithCode) {
|
||||
return p.statusProcessor.Unboost(ctx, authed.Account, authed.Application, targetStatusID)
|
||||
}
|
||||
|
||||
func (p *processor) StatusBoostedBy(authed *oauth.Auth, targetStatusID string) ([]*apimodel.Account, gtserror.WithCode) {
|
||||
return p.statusProcessor.BoostedBy(authed.Account, targetStatusID)
|
||||
func (p *processor) StatusBoostedBy(ctx context.Context, authed *oauth.Auth, targetStatusID string) ([]*apimodel.Account, gtserror.WithCode) {
|
||||
return p.statusProcessor.BoostedBy(ctx, authed.Account, targetStatusID)
|
||||
}
|
||||
|
||||
func (p *processor) StatusFavedBy(authed *oauth.Auth, targetStatusID string) ([]*apimodel.Account, error) {
|
||||
return p.statusProcessor.FavedBy(authed.Account, targetStatusID)
|
||||
func (p *processor) StatusFavedBy(ctx context.Context, authed *oauth.Auth, targetStatusID string) ([]*apimodel.Account, error) {
|
||||
return p.statusProcessor.FavedBy(ctx, authed.Account, targetStatusID)
|
||||
}
|
||||
|
||||
func (p *processor) StatusGet(authed *oauth.Auth, targetStatusID string) (*apimodel.Status, error) {
|
||||
return p.statusProcessor.Get(authed.Account, targetStatusID)
|
||||
func (p *processor) StatusGet(ctx context.Context, authed *oauth.Auth, targetStatusID string) (*apimodel.Status, error) {
|
||||
return p.statusProcessor.Get(ctx, authed.Account, targetStatusID)
|
||||
}
|
||||
|
||||
func (p *processor) StatusUnfave(authed *oauth.Auth, targetStatusID string) (*apimodel.Status, error) {
|
||||
return p.statusProcessor.Unfave(authed.Account, targetStatusID)
|
||||
func (p *processor) StatusUnfave(ctx context.Context, authed *oauth.Auth, targetStatusID string) (*apimodel.Status, error) {
|
||||
return p.statusProcessor.Unfave(ctx, authed.Account, targetStatusID)
|
||||
}
|
||||
|
||||
func (p *processor) StatusGetContext(authed *oauth.Auth, targetStatusID string) (*apimodel.Context, gtserror.WithCode) {
|
||||
return p.statusProcessor.Context(authed.Account, targetStatusID)
|
||||
func (p *processor) StatusGetContext(ctx context.Context, authed *oauth.Auth, targetStatusID string) (*apimodel.Context, gtserror.WithCode) {
|
||||
return p.statusProcessor.Context(ctx, authed.Account, targetStatusID)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,25 @@
|
|||
/*
|
||||
GoToSocial
|
||||
Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package status
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
|
|
@ -9,8 +28,8 @@ import (
|
|||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
)
|
||||
|
||||
func (p *processor) Boost(requestingAccount *gtsmodel.Account, application *gtsmodel.Application, targetStatusID string) (*apimodel.Status, gtserror.WithCode) {
|
||||
targetStatus, err := p.db.GetStatusByID(targetStatusID)
|
||||
func (p *processor) Boost(ctx context.Context, requestingAccount *gtsmodel.Account, application *gtsmodel.Application, targetStatusID string) (*apimodel.Status, gtserror.WithCode) {
|
||||
targetStatus, err := p.db.GetStatusByID(ctx, targetStatusID)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error fetching status %s: %s", targetStatusID, err))
|
||||
}
|
||||
|
|
@ -18,7 +37,7 @@ func (p *processor) Boost(requestingAccount *gtsmodel.Account, application *gtsm
|
|||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("no status owner for status %s", targetStatusID))
|
||||
}
|
||||
|
||||
visible, err := p.filter.StatusVisible(targetStatus, requestingAccount)
|
||||
visible, err := p.filter.StatusVisible(ctx, targetStatus, requestingAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error seeing if status %s is visible: %s", targetStatus.ID, err))
|
||||
}
|
||||
|
|
@ -32,7 +51,7 @@ func (p *processor) Boost(requestingAccount *gtsmodel.Account, application *gtsm
|
|||
}
|
||||
|
||||
// it's visible! it's boostable! so let's boost the FUCK out of it
|
||||
boostWrapperStatus, err := p.tc.StatusToBoost(targetStatus, requestingAccount)
|
||||
boostWrapperStatus, err := p.tc.StatusToBoost(ctx, targetStatus, requestingAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
|
@ -41,7 +60,7 @@ func (p *processor) Boost(requestingAccount *gtsmodel.Account, application *gtsm
|
|||
boostWrapperStatus.BoostOfAccount = targetStatus.Account
|
||||
|
||||
// put the boost in the database
|
||||
if err := p.db.PutStatus(boostWrapperStatus); err != nil {
|
||||
if err := p.db.PutStatus(ctx, boostWrapperStatus); err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
||||
|
|
@ -55,7 +74,7 @@ func (p *processor) Boost(requestingAccount *gtsmodel.Account, application *gtsm
|
|||
}
|
||||
|
||||
// return the frontend representation of the new status to the submitter
|
||||
mastoStatus, err := p.tc.StatusToMasto(boostWrapperStatus, requestingAccount)
|
||||
mastoStatus, err := p.tc.StatusToMasto(ctx, boostWrapperStatus, requestingAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting status %s to frontend representation: %s", targetStatus.ID, err))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,25 @@
|
|||
/*
|
||||
GoToSocial
|
||||
Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package status
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
|
|
@ -9,8 +28,8 @@ import (
|
|||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
)
|
||||
|
||||
func (p *processor) BoostedBy(requestingAccount *gtsmodel.Account, targetStatusID string) ([]*apimodel.Account, gtserror.WithCode) {
|
||||
targetStatus, err := p.db.GetStatusByID(targetStatusID)
|
||||
func (p *processor) BoostedBy(ctx context.Context, requestingAccount *gtsmodel.Account, targetStatusID string) ([]*apimodel.Account, gtserror.WithCode) {
|
||||
targetStatus, err := p.db.GetStatusByID(ctx, targetStatusID)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error fetching status %s: %s", targetStatusID, err))
|
||||
}
|
||||
|
|
@ -18,7 +37,7 @@ func (p *processor) BoostedBy(requestingAccount *gtsmodel.Account, targetStatusI
|
|||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("no status owner for status %s", targetStatusID))
|
||||
}
|
||||
|
||||
visible, err := p.filter.StatusVisible(targetStatus, requestingAccount)
|
||||
visible, err := p.filter.StatusVisible(ctx, targetStatus, requestingAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error seeing if status %s is visible: %s", targetStatus.ID, err))
|
||||
}
|
||||
|
|
@ -26,7 +45,7 @@ func (p *processor) BoostedBy(requestingAccount *gtsmodel.Account, targetStatusI
|
|||
return nil, gtserror.NewErrorNotFound(errors.New("status is not visible"))
|
||||
}
|
||||
|
||||
statusReblogs, err := p.db.GetStatusReblogs(targetStatus)
|
||||
statusReblogs, err := p.db.GetStatusReblogs(ctx, targetStatus)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("StatusBoostedBy: error seeing who boosted status: %s", err))
|
||||
}
|
||||
|
|
@ -34,7 +53,7 @@ func (p *processor) BoostedBy(requestingAccount *gtsmodel.Account, targetStatusI
|
|||
// filter the list so the user doesn't see accounts they blocked or which blocked them
|
||||
filteredAccounts := []*gtsmodel.Account{}
|
||||
for _, s := range statusReblogs {
|
||||
blocked, err := p.db.IsBlocked(requestingAccount.ID, s.AccountID, true)
|
||||
blocked, err := p.db.IsBlocked(ctx, requestingAccount.ID, s.AccountID, true)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("StatusBoostedBy: error checking blocks: %s", err))
|
||||
}
|
||||
|
|
@ -48,7 +67,7 @@ func (p *processor) BoostedBy(requestingAccount *gtsmodel.Account, targetStatusI
|
|||
// now we can return the masto representation of those accounts
|
||||
mastoAccounts := []*apimodel.Account{}
|
||||
for _, acc := range filteredAccounts {
|
||||
mastoAccount, err := p.tc.AccountToMastoPublic(acc)
|
||||
mastoAccount, err := p.tc.AccountToMastoPublic(ctx, acc)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("StatusFavedBy: error converting account to api model: %s", err))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,25 @@
|
|||
/*
|
||||
GoToSocial
|
||||
Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package status
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
|
|
@ -10,8 +29,8 @@ import (
|
|||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
)
|
||||
|
||||
func (p *processor) Context(requestingAccount *gtsmodel.Account, targetStatusID string) (*apimodel.Context, gtserror.WithCode) {
|
||||
targetStatus, err := p.db.GetStatusByID(targetStatusID)
|
||||
func (p *processor) Context(ctx context.Context, requestingAccount *gtsmodel.Account, targetStatusID string) (*apimodel.Context, gtserror.WithCode) {
|
||||
targetStatus, err := p.db.GetStatusByID(ctx, targetStatusID)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error fetching status %s: %s", targetStatusID, err))
|
||||
}
|
||||
|
|
@ -19,7 +38,7 @@ func (p *processor) Context(requestingAccount *gtsmodel.Account, targetStatusID
|
|||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("no status owner for status %s", targetStatusID))
|
||||
}
|
||||
|
||||
visible, err := p.filter.StatusVisible(targetStatus, requestingAccount)
|
||||
visible, err := p.filter.StatusVisible(ctx, targetStatus, requestingAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error seeing if status %s is visible: %s", targetStatus.ID, err))
|
||||
}
|
||||
|
|
@ -32,14 +51,14 @@ func (p *processor) Context(requestingAccount *gtsmodel.Account, targetStatusID
|
|||
Descendants: []apimodel.Status{},
|
||||
}
|
||||
|
||||
parents, err := p.db.GetStatusParents(targetStatus, false)
|
||||
parents, err := p.db.GetStatusParents(ctx, targetStatus, false)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
||||
for _, status := range parents {
|
||||
if v, err := p.filter.StatusVisible(status, requestingAccount); err == nil && v {
|
||||
mastoStatus, err := p.tc.StatusToMasto(status, requestingAccount)
|
||||
if v, err := p.filter.StatusVisible(ctx, status, requestingAccount); err == nil && v {
|
||||
mastoStatus, err := p.tc.StatusToMasto(ctx, status, requestingAccount)
|
||||
if err == nil {
|
||||
context.Ancestors = append(context.Ancestors, *mastoStatus)
|
||||
}
|
||||
|
|
@ -50,14 +69,14 @@ func (p *processor) Context(requestingAccount *gtsmodel.Account, targetStatusID
|
|||
return context.Ancestors[i].ID < context.Ancestors[j].ID
|
||||
})
|
||||
|
||||
children, err := p.db.GetStatusChildren(targetStatus, false, "")
|
||||
children, err := p.db.GetStatusChildren(ctx, targetStatus, false, "")
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
||||
for _, status := range children {
|
||||
if v, err := p.filter.StatusVisible(status, requestingAccount); err == nil && v {
|
||||
mastoStatus, err := p.tc.StatusToMasto(status, requestingAccount)
|
||||
if v, err := p.filter.StatusVisible(ctx, status, requestingAccount); err == nil && v {
|
||||
mastoStatus, err := p.tc.StatusToMasto(ctx, status, requestingAccount)
|
||||
if err == nil {
|
||||
context.Descendants = append(context.Descendants, *mastoStatus)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,25 @@
|
|||
/*
|
||||
GoToSocial
|
||||
Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package status
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
|
|
@ -12,7 +31,7 @@ import (
|
|||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
||||
)
|
||||
|
||||
func (p *processor) Create(account *gtsmodel.Account, application *gtsmodel.Application, form *apimodel.AdvancedStatusCreateForm) (*apimodel.Status, gtserror.WithCode) {
|
||||
func (p *processor) Create(ctx context.Context, account *gtsmodel.Account, application *gtsmodel.Application, form *apimodel.AdvancedStatusCreateForm) (*apimodel.Status, gtserror.WithCode) {
|
||||
uris := util.GenerateURIsForAccount(account.Username, p.config.Protocol, p.config.Host)
|
||||
thisStatusID, err := id.NewULID()
|
||||
if err != nil {
|
||||
|
|
@ -38,40 +57,40 @@ func (p *processor) Create(account *gtsmodel.Account, application *gtsmodel.Appl
|
|||
Text: form.Status,
|
||||
}
|
||||
|
||||
if err := p.ProcessReplyToID(form, account.ID, newStatus); err != nil {
|
||||
if err := p.ProcessReplyToID(ctx, form, account.ID, newStatus); err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
||||
if err := p.ProcessMediaIDs(form, account.ID, newStatus); err != nil {
|
||||
if err := p.ProcessMediaIDs(ctx, form, account.ID, newStatus); err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
||||
if err := p.ProcessVisibility(form, account.Privacy, newStatus); err != nil {
|
||||
if err := p.ProcessVisibility(ctx, form, account.Privacy, newStatus); err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
||||
if err := p.ProcessLanguage(form, account.Language, newStatus); err != nil {
|
||||
if err := p.ProcessLanguage(ctx, form, account.Language, newStatus); err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
||||
if err := p.ProcessMentions(form, account.ID, newStatus); err != nil {
|
||||
if err := p.ProcessMentions(ctx, form, account.ID, newStatus); err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
||||
if err := p.ProcessTags(form, account.ID, newStatus); err != nil {
|
||||
if err := p.ProcessTags(ctx, form, account.ID, newStatus); err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
||||
if err := p.ProcessEmojis(form, account.ID, newStatus); err != nil {
|
||||
if err := p.ProcessEmojis(ctx, form, account.ID, newStatus); err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
||||
if err := p.ProcessContent(form, account.ID, newStatus); err != nil {
|
||||
if err := p.ProcessContent(ctx, form, account.ID, newStatus); err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
||||
// put the new status in the database
|
||||
if err := p.db.PutStatus(newStatus); err != nil {
|
||||
if err := p.db.PutStatus(ctx, newStatus); err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
||||
|
|
@ -84,7 +103,7 @@ func (p *processor) Create(account *gtsmodel.Account, application *gtsmodel.Appl
|
|||
}
|
||||
|
||||
// return the frontend representation of the new status to the submitter
|
||||
mastoStatus, err := p.tc.StatusToMasto(newStatus, account)
|
||||
mastoStatus, err := p.tc.StatusToMasto(ctx, newStatus, account)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting status %s to frontend representation: %s", newStatus.ID, err))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,25 @@
|
|||
/*
|
||||
GoToSocial
|
||||
Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package status
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
|
|
@ -9,8 +28,8 @@ import (
|
|||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
)
|
||||
|
||||
func (p *processor) Delete(requestingAccount *gtsmodel.Account, targetStatusID string) (*apimodel.Status, gtserror.WithCode) {
|
||||
targetStatus, err := p.db.GetStatusByID(targetStatusID)
|
||||
func (p *processor) Delete(ctx context.Context, requestingAccount *gtsmodel.Account, targetStatusID string) (*apimodel.Status, gtserror.WithCode) {
|
||||
targetStatus, err := p.db.GetStatusByID(ctx, targetStatusID)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error fetching status %s: %s", targetStatusID, err))
|
||||
}
|
||||
|
|
@ -22,12 +41,12 @@ func (p *processor) Delete(requestingAccount *gtsmodel.Account, targetStatusID s
|
|||
return nil, gtserror.NewErrorForbidden(errors.New("status doesn't belong to requesting account"))
|
||||
}
|
||||
|
||||
mastoStatus, err := p.tc.StatusToMasto(targetStatus, requestingAccount)
|
||||
mastoStatus, err := p.tc.StatusToMasto(ctx, targetStatus, requestingAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting status %s to frontend representation: %s", targetStatus.ID, err))
|
||||
}
|
||||
|
||||
if err := p.db.DeleteByID(targetStatus.ID, >smodel.Status{}); err != nil {
|
||||
if err := p.db.DeleteByID(ctx, targetStatus.ID, >smodel.Status{}); err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("error deleting status from the database: %s", err))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,25 @@
|
|||
/*
|
||||
GoToSocial
|
||||
Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package status
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
|
|
@ -12,8 +31,8 @@ import (
|
|||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
||||
)
|
||||
|
||||
func (p *processor) Fave(requestingAccount *gtsmodel.Account, targetStatusID string) (*apimodel.Status, gtserror.WithCode) {
|
||||
targetStatus, err := p.db.GetStatusByID(targetStatusID)
|
||||
func (p *processor) Fave(ctx context.Context, requestingAccount *gtsmodel.Account, targetStatusID string) (*apimodel.Status, gtserror.WithCode) {
|
||||
targetStatus, err := p.db.GetStatusByID(ctx, targetStatusID)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error fetching status %s: %s", targetStatusID, err))
|
||||
}
|
||||
|
|
@ -21,7 +40,7 @@ func (p *processor) Fave(requestingAccount *gtsmodel.Account, targetStatusID str
|
|||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("no status owner for status %s", targetStatusID))
|
||||
}
|
||||
|
||||
visible, err := p.filter.StatusVisible(targetStatus, requestingAccount)
|
||||
visible, err := p.filter.StatusVisible(ctx, targetStatus, requestingAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error seeing if status %s is visible: %s", targetStatus.ID, err))
|
||||
}
|
||||
|
|
@ -37,7 +56,7 @@ func (p *processor) Fave(requestingAccount *gtsmodel.Account, targetStatusID str
|
|||
// first check if the status is already faved, if so we don't need to do anything
|
||||
newFave := true
|
||||
gtsFave := >smodel.StatusFave{}
|
||||
if err := p.db.GetWhere([]db.Where{{Key: "status_id", Value: targetStatus.ID}, {Key: "account_id", Value: requestingAccount.ID}}, gtsFave); err == nil {
|
||||
if err := p.db.GetWhere(ctx, []db.Where{{Key: "status_id", Value: targetStatus.ID}, {Key: "account_id", Value: requestingAccount.ID}}, gtsFave); err == nil {
|
||||
// we already have a fave for this status
|
||||
newFave = false
|
||||
}
|
||||
|
|
@ -60,7 +79,7 @@ func (p *processor) Fave(requestingAccount *gtsmodel.Account, targetStatusID str
|
|||
URI: util.GenerateURIForLike(requestingAccount.Username, p.config.Protocol, p.config.Host, thisFaveID),
|
||||
}
|
||||
|
||||
if err := p.db.Put(gtsFave); err != nil {
|
||||
if err := p.db.Put(ctx, gtsFave); err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("error putting fave in database: %s", err))
|
||||
}
|
||||
|
||||
|
|
@ -75,7 +94,7 @@ func (p *processor) Fave(requestingAccount *gtsmodel.Account, targetStatusID str
|
|||
}
|
||||
|
||||
// return the mastodon representation of the target status
|
||||
mastoStatus, err := p.tc.StatusToMasto(targetStatus, requestingAccount)
|
||||
mastoStatus, err := p.tc.StatusToMasto(ctx, targetStatus, requestingAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting status %s to frontend representation: %s", targetStatus.ID, err))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,25 @@
|
|||
/*
|
||||
GoToSocial
|
||||
Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package status
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
|
|
@ -9,8 +28,8 @@ import (
|
|||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
)
|
||||
|
||||
func (p *processor) FavedBy(requestingAccount *gtsmodel.Account, targetStatusID string) ([]*apimodel.Account, gtserror.WithCode) {
|
||||
targetStatus, err := p.db.GetStatusByID(targetStatusID)
|
||||
func (p *processor) FavedBy(ctx context.Context, requestingAccount *gtsmodel.Account, targetStatusID string) ([]*apimodel.Account, gtserror.WithCode) {
|
||||
targetStatus, err := p.db.GetStatusByID(ctx, targetStatusID)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error fetching status %s: %s", targetStatusID, err))
|
||||
}
|
||||
|
|
@ -18,7 +37,7 @@ func (p *processor) FavedBy(requestingAccount *gtsmodel.Account, targetStatusID
|
|||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("no status owner for status %s", targetStatusID))
|
||||
}
|
||||
|
||||
visible, err := p.filter.StatusVisible(targetStatus, requestingAccount)
|
||||
visible, err := p.filter.StatusVisible(ctx, targetStatus, requestingAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error seeing if status %s is visible: %s", targetStatus.ID, err))
|
||||
}
|
||||
|
|
@ -26,7 +45,7 @@ func (p *processor) FavedBy(requestingAccount *gtsmodel.Account, targetStatusID
|
|||
return nil, gtserror.NewErrorNotFound(errors.New("status is not visible"))
|
||||
}
|
||||
|
||||
statusFaves, err := p.db.GetStatusFaves(targetStatus)
|
||||
statusFaves, err := p.db.GetStatusFaves(ctx, targetStatus)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error seeing who faved status: %s", err))
|
||||
}
|
||||
|
|
@ -34,7 +53,7 @@ func (p *processor) FavedBy(requestingAccount *gtsmodel.Account, targetStatusID
|
|||
// filter the list so the user doesn't see accounts they blocked or which blocked them
|
||||
filteredAccounts := []*gtsmodel.Account{}
|
||||
for _, fave := range statusFaves {
|
||||
blocked, err := p.db.IsBlocked(requestingAccount.ID, fave.AccountID, true)
|
||||
blocked, err := p.db.IsBlocked(ctx, requestingAccount.ID, fave.AccountID, true)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("error checking blocks: %s", err))
|
||||
}
|
||||
|
|
@ -46,7 +65,7 @@ func (p *processor) FavedBy(requestingAccount *gtsmodel.Account, targetStatusID
|
|||
// now we can return the masto representation of those accounts
|
||||
mastoAccounts := []*apimodel.Account{}
|
||||
for _, acc := range filteredAccounts {
|
||||
mastoAccount, err := p.tc.AccountToMastoPublic(acc)
|
||||
mastoAccount, err := p.tc.AccountToMastoPublic(ctx, acc)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting status %s to frontend representation: %s", targetStatus.ID, err))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,25 @@
|
|||
/*
|
||||
GoToSocial
|
||||
Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package status
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
|
|
@ -9,8 +28,8 @@ import (
|
|||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
)
|
||||
|
||||
func (p *processor) Get(requestingAccount *gtsmodel.Account, targetStatusID string) (*apimodel.Status, gtserror.WithCode) {
|
||||
targetStatus, err := p.db.GetStatusByID(targetStatusID)
|
||||
func (p *processor) Get(ctx context.Context, requestingAccount *gtsmodel.Account, targetStatusID string) (*apimodel.Status, gtserror.WithCode) {
|
||||
targetStatus, err := p.db.GetStatusByID(ctx, targetStatusID)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error fetching status %s: %s", targetStatusID, err))
|
||||
}
|
||||
|
|
@ -18,7 +37,7 @@ func (p *processor) Get(requestingAccount *gtsmodel.Account, targetStatusID stri
|
|||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("no status owner for status %s", targetStatusID))
|
||||
}
|
||||
|
||||
visible, err := p.filter.StatusVisible(targetStatus, requestingAccount)
|
||||
visible, err := p.filter.StatusVisible(ctx, targetStatus, requestingAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error seeing if status %s is visible: %s", targetStatus.ID, err))
|
||||
}
|
||||
|
|
@ -26,7 +45,7 @@ func (p *processor) Get(requestingAccount *gtsmodel.Account, targetStatusID stri
|
|||
return nil, gtserror.NewErrorNotFound(errors.New("status is not visible"))
|
||||
}
|
||||
|
||||
mastoStatus, err := p.tc.StatusToMasto(targetStatus, requestingAccount)
|
||||
mastoStatus, err := p.tc.StatusToMasto(ctx, targetStatus, requestingAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting status %s to frontend representation: %s", targetStatus.ID, err))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,26 @@
|
|||
/*
|
||||
GoToSocial
|
||||
Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package status
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/config"
|
||||
|
|
@ -15,38 +35,38 @@ import (
|
|||
// Processor wraps a bunch of functions for processing statuses.
|
||||
type Processor interface {
|
||||
// Create processes the given form to create a new status, returning the api model representation of that status if it's OK.
|
||||
Create(account *gtsmodel.Account, application *gtsmodel.Application, form *apimodel.AdvancedStatusCreateForm) (*apimodel.Status, gtserror.WithCode)
|
||||
Create(ctx context.Context, account *gtsmodel.Account, application *gtsmodel.Application, form *apimodel.AdvancedStatusCreateForm) (*apimodel.Status, gtserror.WithCode)
|
||||
// Delete processes the delete of a given status, returning the deleted status if the delete goes through.
|
||||
Delete(account *gtsmodel.Account, targetStatusID string) (*apimodel.Status, gtserror.WithCode)
|
||||
Delete(ctx context.Context, account *gtsmodel.Account, targetStatusID string) (*apimodel.Status, gtserror.WithCode)
|
||||
// Fave processes the faving of a given status, returning the updated status if the fave goes through.
|
||||
Fave(account *gtsmodel.Account, targetStatusID string) (*apimodel.Status, gtserror.WithCode)
|
||||
Fave(ctx context.Context, account *gtsmodel.Account, targetStatusID string) (*apimodel.Status, gtserror.WithCode)
|
||||
// Boost processes the boost/reblog of a given status, returning the newly-created boost if all is well.
|
||||
Boost(account *gtsmodel.Account, application *gtsmodel.Application, targetStatusID string) (*apimodel.Status, gtserror.WithCode)
|
||||
Boost(ctx context.Context, account *gtsmodel.Account, application *gtsmodel.Application, targetStatusID string) (*apimodel.Status, gtserror.WithCode)
|
||||
// Unboost processes the unboost/unreblog of a given status, returning the status if all is well.
|
||||
Unboost(account *gtsmodel.Account, application *gtsmodel.Application, targetStatusID string) (*apimodel.Status, gtserror.WithCode)
|
||||
Unboost(ctx context.Context, account *gtsmodel.Account, application *gtsmodel.Application, targetStatusID string) (*apimodel.Status, gtserror.WithCode)
|
||||
// BoostedBy returns a slice of accounts that have boosted the given status, filtered according to privacy settings.
|
||||
BoostedBy(account *gtsmodel.Account, targetStatusID string) ([]*apimodel.Account, gtserror.WithCode)
|
||||
BoostedBy(ctx context.Context, account *gtsmodel.Account, targetStatusID string) ([]*apimodel.Account, gtserror.WithCode)
|
||||
// FavedBy returns a slice of accounts that have liked the given status, filtered according to privacy settings.
|
||||
FavedBy(account *gtsmodel.Account, targetStatusID string) ([]*apimodel.Account, gtserror.WithCode)
|
||||
FavedBy(ctx context.Context, account *gtsmodel.Account, targetStatusID string) ([]*apimodel.Account, gtserror.WithCode)
|
||||
// Get gets the given status, taking account of privacy settings and blocks etc.
|
||||
Get(account *gtsmodel.Account, targetStatusID string) (*apimodel.Status, gtserror.WithCode)
|
||||
Get(ctx context.Context, account *gtsmodel.Account, targetStatusID string) (*apimodel.Status, gtserror.WithCode)
|
||||
// Unfave processes the unfaving of a given status, returning the updated status if the fave goes through.
|
||||
Unfave(account *gtsmodel.Account, targetStatusID string) (*apimodel.Status, gtserror.WithCode)
|
||||
Unfave(ctx context.Context, account *gtsmodel.Account, targetStatusID string) (*apimodel.Status, gtserror.WithCode)
|
||||
// Context returns the context (previous and following posts) from the given status ID
|
||||
Context(account *gtsmodel.Account, targetStatusID string) (*apimodel.Context, gtserror.WithCode)
|
||||
Context(ctx context.Context, account *gtsmodel.Account, targetStatusID string) (*apimodel.Context, gtserror.WithCode)
|
||||
|
||||
/*
|
||||
PROCESSING UTILS
|
||||
*/
|
||||
|
||||
ProcessVisibility(form *apimodel.AdvancedStatusCreateForm, accountDefaultVis gtsmodel.Visibility, status *gtsmodel.Status) error
|
||||
ProcessReplyToID(form *apimodel.AdvancedStatusCreateForm, thisAccountID string, status *gtsmodel.Status) error
|
||||
ProcessMediaIDs(form *apimodel.AdvancedStatusCreateForm, thisAccountID string, status *gtsmodel.Status) error
|
||||
ProcessLanguage(form *apimodel.AdvancedStatusCreateForm, accountDefaultLanguage string, status *gtsmodel.Status) error
|
||||
ProcessMentions(form *apimodel.AdvancedStatusCreateForm, accountID string, status *gtsmodel.Status) error
|
||||
ProcessTags(form *apimodel.AdvancedStatusCreateForm, accountID string, status *gtsmodel.Status) error
|
||||
ProcessEmojis(form *apimodel.AdvancedStatusCreateForm, accountID string, status *gtsmodel.Status) error
|
||||
ProcessContent(form *apimodel.AdvancedStatusCreateForm, accountID string, status *gtsmodel.Status) error
|
||||
ProcessVisibility(ctx context.Context, form *apimodel.AdvancedStatusCreateForm, accountDefaultVis gtsmodel.Visibility, status *gtsmodel.Status) error
|
||||
ProcessReplyToID(ctx context.Context, form *apimodel.AdvancedStatusCreateForm, thisAccountID string, status *gtsmodel.Status) error
|
||||
ProcessMediaIDs(ctx context.Context, form *apimodel.AdvancedStatusCreateForm, thisAccountID string, status *gtsmodel.Status) error
|
||||
ProcessLanguage(ctx context.Context, form *apimodel.AdvancedStatusCreateForm, accountDefaultLanguage string, status *gtsmodel.Status) error
|
||||
ProcessMentions(ctx context.Context, form *apimodel.AdvancedStatusCreateForm, accountID string, status *gtsmodel.Status) error
|
||||
ProcessTags(ctx context.Context, form *apimodel.AdvancedStatusCreateForm, accountID string, status *gtsmodel.Status) error
|
||||
ProcessEmojis(ctx context.Context, form *apimodel.AdvancedStatusCreateForm, accountID string, status *gtsmodel.Status) error
|
||||
ProcessContent(ctx context.Context, form *apimodel.AdvancedStatusCreateForm, accountID string, status *gtsmodel.Status) error
|
||||
}
|
||||
|
||||
type processor struct {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,25 @@
|
|||
/*
|
||||
GoToSocial
|
||||
Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package status
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
|
|
@ -10,8 +29,8 @@ import (
|
|||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
)
|
||||
|
||||
func (p *processor) Unboost(requestingAccount *gtsmodel.Account, application *gtsmodel.Application, targetStatusID string) (*apimodel.Status, gtserror.WithCode) {
|
||||
targetStatus, err := p.db.GetStatusByID(targetStatusID)
|
||||
func (p *processor) Unboost(ctx context.Context, requestingAccount *gtsmodel.Account, application *gtsmodel.Application, targetStatusID string) (*apimodel.Status, gtserror.WithCode) {
|
||||
targetStatus, err := p.db.GetStatusByID(ctx, targetStatusID)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error fetching status %s: %s", targetStatusID, err))
|
||||
}
|
||||
|
|
@ -19,7 +38,7 @@ func (p *processor) Unboost(requestingAccount *gtsmodel.Account, application *gt
|
|||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("no status owner for status %s", targetStatusID))
|
||||
}
|
||||
|
||||
visible, err := p.filter.StatusVisible(targetStatus, requestingAccount)
|
||||
visible, err := p.filter.StatusVisible(ctx, targetStatus, requestingAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error seeing if status %s is visible: %s", targetStatus.ID, err))
|
||||
}
|
||||
|
|
@ -41,7 +60,7 @@ func (p *processor) Unboost(requestingAccount *gtsmodel.Account, application *gt
|
|||
Value: requestingAccount.ID,
|
||||
},
|
||||
}
|
||||
err = p.db.GetWhere(where, gtsBoost)
|
||||
err = p.db.GetWhere(ctx, where, gtsBoost)
|
||||
if err == nil {
|
||||
// we have a boost
|
||||
toUnboost = true
|
||||
|
|
@ -58,7 +77,7 @@ func (p *processor) Unboost(requestingAccount *gtsmodel.Account, application *gt
|
|||
|
||||
if toUnboost {
|
||||
// we had a boost, so take some action to get rid of it
|
||||
if err := p.db.DeleteWhere(where, >smodel.Status{}); err != nil {
|
||||
if err := p.db.DeleteWhere(ctx, where, >smodel.Status{}); err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("error unboosting status: %s", err))
|
||||
}
|
||||
|
||||
|
|
@ -79,7 +98,7 @@ func (p *processor) Unboost(requestingAccount *gtsmodel.Account, application *gt
|
|||
}
|
||||
}
|
||||
|
||||
mastoStatus, err := p.tc.StatusToMasto(targetStatus, requestingAccount)
|
||||
mastoStatus, err := p.tc.StatusToMasto(ctx, targetStatus, requestingAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting status %s to frontend representation: %s", targetStatus.ID, err))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,25 @@
|
|||
/*
|
||||
GoToSocial
|
||||
Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package status
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
|
|
@ -10,8 +29,8 @@ import (
|
|||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
)
|
||||
|
||||
func (p *processor) Unfave(requestingAccount *gtsmodel.Account, targetStatusID string) (*apimodel.Status, gtserror.WithCode) {
|
||||
targetStatus, err := p.db.GetStatusByID(targetStatusID)
|
||||
func (p *processor) Unfave(ctx context.Context, requestingAccount *gtsmodel.Account, targetStatusID string) (*apimodel.Status, gtserror.WithCode) {
|
||||
targetStatus, err := p.db.GetStatusByID(ctx, targetStatusID)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error fetching status %s: %s", targetStatusID, err))
|
||||
}
|
||||
|
|
@ -19,7 +38,7 @@ func (p *processor) Unfave(requestingAccount *gtsmodel.Account, targetStatusID s
|
|||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("no status owner for status %s", targetStatusID))
|
||||
}
|
||||
|
||||
visible, err := p.filter.StatusVisible(targetStatus, requestingAccount)
|
||||
visible, err := p.filter.StatusVisible(ctx, targetStatus, requestingAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error seeing if status %s is visible: %s", targetStatus.ID, err))
|
||||
}
|
||||
|
|
@ -31,7 +50,7 @@ func (p *processor) Unfave(requestingAccount *gtsmodel.Account, targetStatusID s
|
|||
var toUnfave bool
|
||||
|
||||
gtsFave := >smodel.StatusFave{}
|
||||
err = p.db.GetWhere([]db.Where{{Key: "status_id", Value: targetStatus.ID}, {Key: "account_id", Value: requestingAccount.ID}}, gtsFave)
|
||||
err = p.db.GetWhere(ctx, []db.Where{{Key: "status_id", Value: targetStatus.ID}, {Key: "account_id", Value: requestingAccount.ID}}, gtsFave)
|
||||
if err == nil {
|
||||
// we have a fave
|
||||
toUnfave = true
|
||||
|
|
@ -47,7 +66,7 @@ func (p *processor) Unfave(requestingAccount *gtsmodel.Account, targetStatusID s
|
|||
|
||||
if toUnfave {
|
||||
// we had a fave, so take some action to get rid of it
|
||||
if err := p.db.DeleteWhere([]db.Where{{Key: "status_id", Value: targetStatus.ID}, {Key: "account_id", Value: requestingAccount.ID}}, gtsFave); err != nil {
|
||||
if err := p.db.DeleteWhere(ctx, []db.Where{{Key: "status_id", Value: targetStatus.ID}, {Key: "account_id", Value: requestingAccount.ID}}, gtsFave); err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("error unfaveing status: %s", err))
|
||||
}
|
||||
|
||||
|
|
@ -61,7 +80,7 @@ func (p *processor) Unfave(requestingAccount *gtsmodel.Account, targetStatusID s
|
|||
}
|
||||
}
|
||||
|
||||
mastoStatus, err := p.tc.StatusToMasto(targetStatus, requestingAccount)
|
||||
mastoStatus, err := p.tc.StatusToMasto(ctx, targetStatus, requestingAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting status %s to frontend representation: %s", targetStatus.ID, err))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,25 @@
|
|||
/*
|
||||
GoToSocial
|
||||
Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package status
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
|
|
@ -12,7 +31,7 @@ import (
|
|||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
||||
)
|
||||
|
||||
func (p *processor) ProcessVisibility(form *apimodel.AdvancedStatusCreateForm, accountDefaultVis gtsmodel.Visibility, status *gtsmodel.Status) error {
|
||||
func (p *processor) ProcessVisibility(ctx context.Context, form *apimodel.AdvancedStatusCreateForm, accountDefaultVis gtsmodel.Visibility, status *gtsmodel.Status) error {
|
||||
// by default all flags are set to true
|
||||
gtsAdvancedVis := >smodel.VisibilityAdvanced{
|
||||
Federated: true,
|
||||
|
|
@ -83,7 +102,7 @@ func (p *processor) ProcessVisibility(form *apimodel.AdvancedStatusCreateForm, a
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *processor) ProcessReplyToID(form *apimodel.AdvancedStatusCreateForm, thisAccountID string, status *gtsmodel.Status) error {
|
||||
func (p *processor) ProcessReplyToID(ctx context.Context, form *apimodel.AdvancedStatusCreateForm, thisAccountID string, status *gtsmodel.Status) error {
|
||||
if form.InReplyToID == "" {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -98,7 +117,7 @@ func (p *processor) ProcessReplyToID(form *apimodel.AdvancedStatusCreateForm, th
|
|||
repliedStatus := >smodel.Status{}
|
||||
repliedAccount := >smodel.Account{}
|
||||
// check replied status exists + is replyable
|
||||
if err := p.db.GetByID(form.InReplyToID, repliedStatus); err != nil {
|
||||
if err := p.db.GetByID(ctx, form.InReplyToID, repliedStatus); err != nil {
|
||||
if err == db.ErrNoEntries {
|
||||
return fmt.Errorf("status with id %s not replyable because it doesn't exist", form.InReplyToID)
|
||||
}
|
||||
|
|
@ -112,14 +131,14 @@ func (p *processor) ProcessReplyToID(form *apimodel.AdvancedStatusCreateForm, th
|
|||
}
|
||||
|
||||
// check replied account is known to us
|
||||
if err := p.db.GetByID(repliedStatus.AccountID, repliedAccount); err != nil {
|
||||
if err := p.db.GetByID(ctx, repliedStatus.AccountID, repliedAccount); err != nil {
|
||||
if err == db.ErrNoEntries {
|
||||
return fmt.Errorf("status with id %s not replyable because account id %s is not known", form.InReplyToID, repliedStatus.AccountID)
|
||||
}
|
||||
return fmt.Errorf("status with id %s not replyable: %s", form.InReplyToID, err)
|
||||
}
|
||||
// check if a block exists
|
||||
if blocked, err := p.db.IsBlocked(thisAccountID, repliedAccount.ID, true); err != nil {
|
||||
if blocked, err := p.db.IsBlocked(ctx, thisAccountID, repliedAccount.ID, true); err != nil {
|
||||
if err != db.ErrNoEntries {
|
||||
return fmt.Errorf("status with id %s not replyable: %s", form.InReplyToID, err)
|
||||
}
|
||||
|
|
@ -132,7 +151,7 @@ func (p *processor) ProcessReplyToID(form *apimodel.AdvancedStatusCreateForm, th
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *processor) ProcessMediaIDs(form *apimodel.AdvancedStatusCreateForm, thisAccountID string, status *gtsmodel.Status) error {
|
||||
func (p *processor) ProcessMediaIDs(ctx context.Context, form *apimodel.AdvancedStatusCreateForm, thisAccountID string, status *gtsmodel.Status) error {
|
||||
if form.MediaIDs == nil {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -142,7 +161,7 @@ func (p *processor) ProcessMediaIDs(form *apimodel.AdvancedStatusCreateForm, thi
|
|||
for _, mediaID := range form.MediaIDs {
|
||||
// check these attachments exist
|
||||
a := >smodel.MediaAttachment{}
|
||||
if err := p.db.GetByID(mediaID, a); err != nil {
|
||||
if err := p.db.GetByID(ctx, mediaID, a); err != nil {
|
||||
return fmt.Errorf("invalid media type or media not found for media id %s", mediaID)
|
||||
}
|
||||
// check they belong to the requesting account id
|
||||
|
|
@ -161,7 +180,7 @@ func (p *processor) ProcessMediaIDs(form *apimodel.AdvancedStatusCreateForm, thi
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *processor) ProcessLanguage(form *apimodel.AdvancedStatusCreateForm, accountDefaultLanguage string, status *gtsmodel.Status) error {
|
||||
func (p *processor) ProcessLanguage(ctx context.Context, form *apimodel.AdvancedStatusCreateForm, accountDefaultLanguage string, status *gtsmodel.Status) error {
|
||||
if form.Language != "" {
|
||||
status.Language = form.Language
|
||||
} else {
|
||||
|
|
@ -173,9 +192,9 @@ func (p *processor) ProcessLanguage(form *apimodel.AdvancedStatusCreateForm, acc
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *processor) ProcessMentions(form *apimodel.AdvancedStatusCreateForm, accountID string, status *gtsmodel.Status) error {
|
||||
func (p *processor) ProcessMentions(ctx context.Context, form *apimodel.AdvancedStatusCreateForm, accountID string, status *gtsmodel.Status) error {
|
||||
menchies := []string{}
|
||||
gtsMenchies, err := p.db.MentionStringsToMentions(util.DeriveMentionsFromStatus(form.Status), accountID, status.ID)
|
||||
gtsMenchies, err := p.db.MentionStringsToMentions(ctx, util.DeriveMentionsFromStatus(form.Status), accountID, status.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error generating mentions from status: %s", err)
|
||||
}
|
||||
|
|
@ -186,7 +205,7 @@ func (p *processor) ProcessMentions(form *apimodel.AdvancedStatusCreateForm, acc
|
|||
}
|
||||
menchie.ID = menchieID
|
||||
|
||||
if err := p.db.Put(menchie); err != nil {
|
||||
if err := p.db.Put(ctx, menchie); err != nil {
|
||||
return fmt.Errorf("error putting mentions in db: %s", err)
|
||||
}
|
||||
menchies = append(menchies, menchie.ID)
|
||||
|
|
@ -198,14 +217,14 @@ func (p *processor) ProcessMentions(form *apimodel.AdvancedStatusCreateForm, acc
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *processor) ProcessTags(form *apimodel.AdvancedStatusCreateForm, accountID string, status *gtsmodel.Status) error {
|
||||
func (p *processor) ProcessTags(ctx context.Context, form *apimodel.AdvancedStatusCreateForm, accountID string, status *gtsmodel.Status) error {
|
||||
tags := []string{}
|
||||
gtsTags, err := p.db.TagStringsToTags(util.DeriveHashtagsFromStatus(form.Status), accountID, status.ID)
|
||||
gtsTags, err := p.db.TagStringsToTags(ctx, util.DeriveHashtagsFromStatus(form.Status), accountID, status.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error generating hashtags from status: %s", err)
|
||||
}
|
||||
for _, tag := range gtsTags {
|
||||
if err := p.db.Upsert(tag, "name"); err != nil {
|
||||
if err := p.db.Upsert(ctx, tag, "name"); err != nil {
|
||||
return fmt.Errorf("error putting tags in db: %s", err)
|
||||
}
|
||||
tags = append(tags, tag.ID)
|
||||
|
|
@ -217,9 +236,9 @@ func (p *processor) ProcessTags(form *apimodel.AdvancedStatusCreateForm, account
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *processor) ProcessEmojis(form *apimodel.AdvancedStatusCreateForm, accountID string, status *gtsmodel.Status) error {
|
||||
func (p *processor) ProcessEmojis(ctx context.Context, form *apimodel.AdvancedStatusCreateForm, accountID string, status *gtsmodel.Status) error {
|
||||
emojis := []string{}
|
||||
gtsEmojis, err := p.db.EmojiStringsToEmojis(util.DeriveEmojisFromStatus(form.Status), accountID, status.ID)
|
||||
gtsEmojis, err := p.db.EmojiStringsToEmojis(ctx, util.DeriveEmojisFromStatus(form.Status), accountID, status.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error generating emojis from status: %s", err)
|
||||
}
|
||||
|
|
@ -233,7 +252,7 @@ func (p *processor) ProcessEmojis(form *apimodel.AdvancedStatusCreateForm, accou
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *processor) ProcessContent(form *apimodel.AdvancedStatusCreateForm, accountID string, status *gtsmodel.Status) error {
|
||||
func (p *processor) ProcessContent(ctx context.Context, form *apimodel.AdvancedStatusCreateForm, accountID string, status *gtsmodel.Status) error {
|
||||
// if there's nothing in the status at all we can just return early
|
||||
if form.Status == "" {
|
||||
status.Content = ""
|
||||
|
|
@ -252,9 +271,9 @@ func (p *processor) ProcessContent(form *apimodel.AdvancedStatusCreateForm, acco
|
|||
var formatted string
|
||||
switch form.Format {
|
||||
case apimodel.StatusFormatPlain:
|
||||
formatted = p.formatter.FromPlain(content, status.Mentions, status.Tags)
|
||||
formatted = p.formatter.FromPlain(ctx, content, status.Mentions, status.Tags)
|
||||
case apimodel.StatusFormatMarkdown:
|
||||
formatted = p.formatter.FromMarkdown(content, status.Mentions, status.Tags)
|
||||
formatted = p.formatter.FromMarkdown(ctx, content, status.Mentions, status.Tags)
|
||||
default:
|
||||
return fmt.Errorf("format %s not recognised as a valid status format", form.Format)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,25 @@
|
|||
/*
|
||||
GoToSocial
|
||||
Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package status_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
|
|
@ -88,7 +107,7 @@ func (suite *UtilTestSuite) TestProcessMentions1() {
|
|||
ID: "01FCTDD78JJMX3K9KPXQ7ZQ8BJ",
|
||||
}
|
||||
|
||||
err := suite.status.ProcessMentions(form, creatingAccount.ID, status)
|
||||
err := suite.status.ProcessMentions(context.Background(), form, creatingAccount.ID, status)
|
||||
assert.NoError(suite.T(), err)
|
||||
|
||||
assert.Len(suite.T(), status.Mentions, 1)
|
||||
|
|
@ -138,11 +157,11 @@ func (suite *UtilTestSuite) TestProcessContentFull1() {
|
|||
ID: "01FCTDD78JJMX3K9KPXQ7ZQ8BJ",
|
||||
}
|
||||
|
||||
err := suite.status.ProcessMentions(form, creatingAccount.ID, status)
|
||||
err := suite.status.ProcessMentions(context.Background(), form, creatingAccount.ID, status)
|
||||
assert.NoError(suite.T(), err)
|
||||
assert.Empty(suite.T(), status.Content) // shouldn't be set yet
|
||||
|
||||
err = suite.status.ProcessTags(form, creatingAccount.ID, status)
|
||||
err = suite.status.ProcessTags(context.Background(), form, creatingAccount.ID, status)
|
||||
assert.NoError(suite.T(), err)
|
||||
assert.Empty(suite.T(), status.Content) // shouldn't be set yet
|
||||
|
||||
|
|
@ -150,7 +169,7 @@ func (suite *UtilTestSuite) TestProcessContentFull1() {
|
|||
ACTUAL TEST
|
||||
*/
|
||||
|
||||
err = suite.status.ProcessContent(form, creatingAccount.ID, status)
|
||||
err = suite.status.ProcessContent(context.Background(), form, creatingAccount.ID, status)
|
||||
assert.NoError(suite.T(), err)
|
||||
assert.Equal(suite.T(), statusText1ExpectedFull, status.Content)
|
||||
}
|
||||
|
|
@ -187,7 +206,7 @@ func (suite *UtilTestSuite) TestProcessContentPartial1() {
|
|||
ID: "01FCTDD78JJMX3K9KPXQ7ZQ8BJ",
|
||||
}
|
||||
|
||||
err := suite.status.ProcessMentions(form, creatingAccount.ID, status)
|
||||
err := suite.status.ProcessMentions(context.Background(), form, creatingAccount.ID, status)
|
||||
assert.NoError(suite.T(), err)
|
||||
assert.Empty(suite.T(), status.Content) // shouldn't be set yet
|
||||
|
||||
|
|
@ -195,7 +214,7 @@ func (suite *UtilTestSuite) TestProcessContentPartial1() {
|
|||
ACTUAL TEST
|
||||
*/
|
||||
|
||||
err = suite.status.ProcessContent(form, creatingAccount.ID, status)
|
||||
err = suite.status.ProcessContent(context.Background(), form, creatingAccount.ID, status)
|
||||
assert.NoError(suite.T(), err)
|
||||
assert.Equal(suite.T(), statusText1ExpectedPartial, status.Content)
|
||||
}
|
||||
|
|
@ -229,7 +248,7 @@ func (suite *UtilTestSuite) TestProcessMentions2() {
|
|||
ID: "01FCTDD78JJMX3K9KPXQ7ZQ8BJ",
|
||||
}
|
||||
|
||||
err := suite.status.ProcessMentions(form, creatingAccount.ID, status)
|
||||
err := suite.status.ProcessMentions(context.Background(), form, creatingAccount.ID, status)
|
||||
assert.NoError(suite.T(), err)
|
||||
|
||||
assert.Len(suite.T(), status.Mentions, 1)
|
||||
|
|
@ -279,11 +298,11 @@ func (suite *UtilTestSuite) TestProcessContentFull2() {
|
|||
ID: "01FCTDD78JJMX3K9KPXQ7ZQ8BJ",
|
||||
}
|
||||
|
||||
err := suite.status.ProcessMentions(form, creatingAccount.ID, status)
|
||||
err := suite.status.ProcessMentions(context.Background(), form, creatingAccount.ID, status)
|
||||
assert.NoError(suite.T(), err)
|
||||
assert.Empty(suite.T(), status.Content) // shouldn't be set yet
|
||||
|
||||
err = suite.status.ProcessTags(form, creatingAccount.ID, status)
|
||||
err = suite.status.ProcessTags(context.Background(), form, creatingAccount.ID, status)
|
||||
assert.NoError(suite.T(), err)
|
||||
assert.Empty(suite.T(), status.Content) // shouldn't be set yet
|
||||
|
||||
|
|
@ -291,7 +310,7 @@ func (suite *UtilTestSuite) TestProcessContentFull2() {
|
|||
ACTUAL TEST
|
||||
*/
|
||||
|
||||
err = suite.status.ProcessContent(form, creatingAccount.ID, status)
|
||||
err = suite.status.ProcessContent(context.Background(), form, creatingAccount.ID, status)
|
||||
assert.NoError(suite.T(), err)
|
||||
|
||||
assert.Equal(suite.T(), status2TextExpectedFull, status.Content)
|
||||
|
|
@ -329,7 +348,7 @@ func (suite *UtilTestSuite) TestProcessContentPartial2() {
|
|||
ID: "01FCTDD78JJMX3K9KPXQ7ZQ8BJ",
|
||||
}
|
||||
|
||||
err := suite.status.ProcessMentions(form, creatingAccount.ID, status)
|
||||
err := suite.status.ProcessMentions(context.Background(), form, creatingAccount.ID, status)
|
||||
assert.NoError(suite.T(), err)
|
||||
assert.Empty(suite.T(), status.Content) // shouldn't be set yet
|
||||
|
||||
|
|
@ -337,7 +356,7 @@ func (suite *UtilTestSuite) TestProcessContentPartial2() {
|
|||
ACTUAL TEST
|
||||
*/
|
||||
|
||||
err = suite.status.ProcessContent(form, creatingAccount.ID, status)
|
||||
err = suite.status.ProcessContent(context.Background(), form, creatingAccount.ID, status)
|
||||
assert.NoError(suite.T(), err)
|
||||
|
||||
fmt.Println(status.Content)
|
||||
|
|
|
|||
|
|
@ -19,14 +19,16 @@
|
|||
package processing
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
)
|
||||
|
||||
func (p *processor) AuthorizeStreamingRequest(accessToken string) (*gtsmodel.Account, error) {
|
||||
return p.streamingProcessor.AuthorizeStreamingRequest(accessToken)
|
||||
func (p *processor) AuthorizeStreamingRequest(ctx context.Context, accessToken string) (*gtsmodel.Account, error) {
|
||||
return p.streamingProcessor.AuthorizeStreamingRequest(ctx, accessToken)
|
||||
}
|
||||
|
||||
func (p *processor) OpenStreamForAccount(account *gtsmodel.Account, streamType string) (*gtsmodel.Stream, gtserror.WithCode) {
|
||||
return p.streamingProcessor.OpenStreamForAccount(account, streamType)
|
||||
func (p *processor) OpenStreamForAccount(ctx context.Context, account *gtsmodel.Account, streamType string) (*gtsmodel.Stream, gtserror.WithCode) {
|
||||
return p.streamingProcessor.OpenStreamForAccount(ctx, account, streamType)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import (
|
|||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
)
|
||||
|
||||
func (p *processor) AuthorizeStreamingRequest(accessToken string) (*gtsmodel.Account, error) {
|
||||
func (p *processor) AuthorizeStreamingRequest(ctx context.Context, accessToken string) (*gtsmodel.Account, error) {
|
||||
ti, err := p.oauthServer.LoadAccessToken(context.Background(), accessToken)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("AuthorizeStreamingRequest: error loading access token: %s", err)
|
||||
|
|
@ -20,12 +20,12 @@ func (p *processor) AuthorizeStreamingRequest(accessToken string) (*gtsmodel.Acc
|
|||
|
||||
// fetch user's and account for this user id
|
||||
user := >smodel.User{}
|
||||
if err := p.db.GetByID(uid, user); err != nil || user == nil {
|
||||
if err := p.db.GetByID(ctx, uid, user); err != nil || user == nil {
|
||||
return nil, fmt.Errorf("AuthorizeStreamingRequest: no user found for validated uid %s", uid)
|
||||
}
|
||||
|
||||
acct := >smodel.Account{}
|
||||
if err := p.db.GetByID(user.AccountID, acct); err != nil || acct == nil {
|
||||
if err := p.db.GetByID(ctx, user.AccountID, acct); err != nil || acct == nil {
|
||||
return nil, fmt.Errorf("AuthorizeStreamingRequest: no account retrieved for user with id %s", uid)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package streaming
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
|
|
@ -10,7 +11,7 @@ import (
|
|||
"github.com/superseriousbusiness/gotosocial/internal/id"
|
||||
)
|
||||
|
||||
func (p *processor) OpenStreamForAccount(account *gtsmodel.Account, streamType string) (*gtsmodel.Stream, gtserror.WithCode) {
|
||||
func (p *processor) OpenStreamForAccount(ctx context.Context, account *gtsmodel.Account, streamType string) (*gtsmodel.Stream, gtserror.WithCode) {
|
||||
l := p.log.WithFields(logrus.Fields{
|
||||
"func": "OpenStreamForAccount",
|
||||
"account": account.ID,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package streaming
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
|
|
@ -17,9 +18,9 @@ import (
|
|||
// Processor wraps a bunch of functions for processing streaming.
|
||||
type Processor interface {
|
||||
// AuthorizeStreamingRequest returns an oauth2 token info in response to an access token query from the streaming API
|
||||
AuthorizeStreamingRequest(accessToken string) (*gtsmodel.Account, error)
|
||||
AuthorizeStreamingRequest(ctx context.Context, accessToken string) (*gtsmodel.Account, error)
|
||||
// OpenStreamForAccount returns a new Stream for the given account, which will contain a channel for passing messages back to the caller.
|
||||
OpenStreamForAccount(account *gtsmodel.Account, streamType string) (*gtsmodel.Stream, gtserror.WithCode)
|
||||
OpenStreamForAccount(ctx context.Context, account *gtsmodel.Account, streamType string) (*gtsmodel.Stream, gtserror.WithCode)
|
||||
// StreamStatusToAccount streams the given status to any open, appropriate streams belonging to the given account.
|
||||
StreamStatusToAccount(s *apimodel.Status, account *gtsmodel.Account) error
|
||||
// StreamNotificationToAccount streams the given notification to any open, appropriate streams belonging to the given account.
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
package processing
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
|
|
@ -58,8 +59,8 @@ func (p *processor) packageStatusResponse(statuses []*apimodel.Status, path stri
|
|||
return resp, nil
|
||||
}
|
||||
|
||||
func (p *processor) HomeTimelineGet(authed *oauth.Auth, maxID string, sinceID string, minID string, limit int, local bool) (*apimodel.StatusTimelineResponse, gtserror.WithCode) {
|
||||
statuses, err := p.timelineManager.HomeTimeline(authed.Account.ID, maxID, sinceID, minID, limit, local)
|
||||
func (p *processor) HomeTimelineGet(ctx context.Context, authed *oauth.Auth, maxID string, sinceID string, minID string, limit int, local bool) (*apimodel.StatusTimelineResponse, gtserror.WithCode) {
|
||||
statuses, err := p.timelineManager.HomeTimeline(ctx, authed.Account.ID, maxID, sinceID, minID, limit, local)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
|
@ -73,8 +74,8 @@ func (p *processor) HomeTimelineGet(authed *oauth.Auth, maxID string, sinceID st
|
|||
return p.packageStatusResponse(statuses, "api/v1/timelines/home", statuses[len(statuses)-1].ID, statuses[0].ID, limit)
|
||||
}
|
||||
|
||||
func (p *processor) PublicTimelineGet(authed *oauth.Auth, maxID string, sinceID string, minID string, limit int, local bool) (*apimodel.StatusTimelineResponse, gtserror.WithCode) {
|
||||
statuses, err := p.db.GetPublicTimeline(authed.Account.ID, maxID, sinceID, minID, limit, local)
|
||||
func (p *processor) PublicTimelineGet(ctx context.Context, authed *oauth.Auth, maxID string, sinceID string, minID string, limit int, local bool) (*apimodel.StatusTimelineResponse, gtserror.WithCode) {
|
||||
statuses, err := p.db.GetPublicTimeline(ctx, authed.Account.ID, maxID, sinceID, minID, limit, local)
|
||||
if err != nil {
|
||||
if err == db.ErrNoEntries {
|
||||
// there are just no entries left
|
||||
|
|
@ -86,7 +87,7 @@ func (p *processor) PublicTimelineGet(authed *oauth.Auth, maxID string, sinceID
|
|||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
||||
s, err := p.filterPublicStatuses(authed, statuses)
|
||||
s, err := p.filterPublicStatuses(ctx, authed, statuses)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
|
@ -94,8 +95,8 @@ func (p *processor) PublicTimelineGet(authed *oauth.Auth, maxID string, sinceID
|
|||
return p.packageStatusResponse(s, "api/v1/timelines/public", s[len(s)-1].ID, s[0].ID, limit)
|
||||
}
|
||||
|
||||
func (p *processor) FavedTimelineGet(authed *oauth.Auth, maxID string, minID string, limit int) (*apimodel.StatusTimelineResponse, gtserror.WithCode) {
|
||||
statuses, nextMaxID, prevMinID, err := p.db.GetFavedTimeline(authed.Account.ID, maxID, minID, limit)
|
||||
func (p *processor) FavedTimelineGet(ctx context.Context, authed *oauth.Auth, maxID string, minID string, limit int) (*apimodel.StatusTimelineResponse, gtserror.WithCode) {
|
||||
statuses, nextMaxID, prevMinID, err := p.db.GetFavedTimeline(ctx, authed.Account.ID, maxID, minID, limit)
|
||||
if err != nil {
|
||||
if err == db.ErrNoEntries {
|
||||
// there are just no entries left
|
||||
|
|
@ -107,7 +108,7 @@ func (p *processor) FavedTimelineGet(authed *oauth.Auth, maxID string, minID str
|
|||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
||||
s, err := p.filterFavedStatuses(authed, statuses)
|
||||
s, err := p.filterFavedStatuses(ctx, authed, statuses)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
|
@ -115,13 +116,13 @@ func (p *processor) FavedTimelineGet(authed *oauth.Auth, maxID string, minID str
|
|||
return p.packageStatusResponse(s, "api/v1/favourites", nextMaxID, prevMinID, limit)
|
||||
}
|
||||
|
||||
func (p *processor) filterPublicStatuses(authed *oauth.Auth, statuses []*gtsmodel.Status) ([]*apimodel.Status, error) {
|
||||
func (p *processor) filterPublicStatuses(ctx context.Context, authed *oauth.Auth, statuses []*gtsmodel.Status) ([]*apimodel.Status, error) {
|
||||
l := p.log.WithField("func", "filterPublicStatuses")
|
||||
|
||||
apiStatuses := []*apimodel.Status{}
|
||||
for _, s := range statuses {
|
||||
targetAccount := >smodel.Account{}
|
||||
if err := p.db.GetByID(s.AccountID, targetAccount); err != nil {
|
||||
if err := p.db.GetByID(ctx, s.AccountID, targetAccount); err != nil {
|
||||
if err == db.ErrNoEntries {
|
||||
l.Debugf("filterPublicStatuses: skipping status %s because account %s can't be found in the db", s.ID, s.AccountID)
|
||||
continue
|
||||
|
|
@ -129,7 +130,7 @@ func (p *processor) filterPublicStatuses(authed *oauth.Auth, statuses []*gtsmode
|
|||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("filterPublicStatuses: error getting status author: %s", err))
|
||||
}
|
||||
|
||||
timelineable, err := p.filter.StatusPublictimelineable(s, authed.Account)
|
||||
timelineable, err := p.filter.StatusPublictimelineable(ctx, s, authed.Account)
|
||||
if err != nil {
|
||||
l.Debugf("filterPublicStatuses: skipping status %s because of an error checking status visibility: %s", s.ID, err)
|
||||
continue
|
||||
|
|
@ -138,7 +139,7 @@ func (p *processor) filterPublicStatuses(authed *oauth.Auth, statuses []*gtsmode
|
|||
continue
|
||||
}
|
||||
|
||||
apiStatus, err := p.tc.StatusToMasto(s, authed.Account)
|
||||
apiStatus, err := p.tc.StatusToMasto(ctx, s, authed.Account)
|
||||
if err != nil {
|
||||
l.Debugf("filterPublicStatuses: skipping status %s because it couldn't be converted to its mastodon representation: %s", s.ID, err)
|
||||
continue
|
||||
|
|
@ -150,13 +151,13 @@ func (p *processor) filterPublicStatuses(authed *oauth.Auth, statuses []*gtsmode
|
|||
return apiStatuses, nil
|
||||
}
|
||||
|
||||
func (p *processor) filterFavedStatuses(authed *oauth.Auth, statuses []*gtsmodel.Status) ([]*apimodel.Status, error) {
|
||||
func (p *processor) filterFavedStatuses(ctx context.Context, authed *oauth.Auth, statuses []*gtsmodel.Status) ([]*apimodel.Status, error) {
|
||||
l := p.log.WithField("func", "filterFavedStatuses")
|
||||
|
||||
apiStatuses := []*apimodel.Status{}
|
||||
for _, s := range statuses {
|
||||
targetAccount := >smodel.Account{}
|
||||
if err := p.db.GetByID(s.AccountID, targetAccount); err != nil {
|
||||
if err := p.db.GetByID(ctx, s.AccountID, targetAccount); err != nil {
|
||||
if err == db.ErrNoEntries {
|
||||
l.Debugf("filterFavedStatuses: skipping status %s because account %s can't be found in the db", s.ID, s.AccountID)
|
||||
continue
|
||||
|
|
@ -164,7 +165,7 @@ func (p *processor) filterFavedStatuses(authed *oauth.Auth, statuses []*gtsmodel
|
|||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("filterPublicStatuses: error getting status author: %s", err))
|
||||
}
|
||||
|
||||
timelineable, err := p.filter.StatusVisible(s, authed.Account)
|
||||
timelineable, err := p.filter.StatusVisible(ctx, s, authed.Account)
|
||||
if err != nil {
|
||||
l.Debugf("filterFavedStatuses: skipping status %s because of an error checking status visibility: %s", s.ID, err)
|
||||
continue
|
||||
|
|
@ -173,7 +174,7 @@ func (p *processor) filterFavedStatuses(authed *oauth.Auth, statuses []*gtsmodel
|
|||
continue
|
||||
}
|
||||
|
||||
apiStatus, err := p.tc.StatusToMasto(s, authed.Account)
|
||||
apiStatus, err := p.tc.StatusToMasto(ctx, s, authed.Account)
|
||||
if err != nil {
|
||||
l.Debugf("filterFavedStatuses: skipping status %s because it couldn't be converted to its mastodon representation: %s", s.ID, err)
|
||||
continue
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ func NewTestDB() db.DB {
|
|||
l.SetLevel(logrus.TraceLevel)
|
||||
testDB, err := pg.NewPostgresService(context.Background(), config, l)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
logrus.Panic(err)
|
||||
}
|
||||
return testDB
|
||||
}
|
||||
|
|
@ -84,115 +84,124 @@ func NewTestDB() db.DB {
|
|||
// signatures with, otherwise this function will randomly generate new keys for accounts and signature
|
||||
// verification will fail.
|
||||
func StandardDBSetup(db db.DB, accounts map[string]*gtsmodel.Account) {
|
||||
if db == nil {
|
||||
logrus.Panic("db setup: db was nil")
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
for _, m := range testModels {
|
||||
if err := db.CreateTable(ctx, m); err != nil {
|
||||
panic(err)
|
||||
logrus.Panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, v := range NewTestTokens() {
|
||||
if err := db.Put(ctx, v); err != nil {
|
||||
panic(err)
|
||||
logrus.Panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, v := range NewTestClients() {
|
||||
if err := db.Put(ctx, v); err != nil {
|
||||
panic(err)
|
||||
logrus.Panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, v := range NewTestApplications() {
|
||||
if err := db.Put(ctx, v); err != nil {
|
||||
panic(err)
|
||||
logrus.Panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, v := range NewTestUsers() {
|
||||
if err := db.Put(ctx, v); err != nil {
|
||||
panic(err)
|
||||
logrus.Panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
if accounts == nil {
|
||||
for _, v := range NewTestAccounts() {
|
||||
if err := db.Put(ctx, v); err != nil {
|
||||
panic(err)
|
||||
logrus.Panic(err)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for _, v := range accounts {
|
||||
if err := db.Put(ctx, v); err != nil {
|
||||
panic(err)
|
||||
logrus.Panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, v := range NewTestAttachments() {
|
||||
if err := db.Put(ctx, v); err != nil {
|
||||
panic(err)
|
||||
logrus.Panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, v := range NewTestStatuses() {
|
||||
if err := db.PutStatus(ctx, v); err != nil {
|
||||
panic(err)
|
||||
logrus.Panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, v := range NewTestEmojis() {
|
||||
if err := db.Put(ctx, v); err != nil {
|
||||
panic(err)
|
||||
logrus.Panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, v := range NewTestTags() {
|
||||
if err := db.Put(ctx, v); err != nil {
|
||||
panic(err)
|
||||
logrus.Panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, v := range NewTestMentions() {
|
||||
if err := db.Put(ctx, v); err != nil {
|
||||
panic(err)
|
||||
logrus.Panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, v := range NewTestFaves() {
|
||||
if err := db.Put(ctx, v); err != nil {
|
||||
panic(err)
|
||||
logrus.Panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, v := range NewTestFollows() {
|
||||
if err := db.Put(ctx, v); err != nil {
|
||||
panic(err)
|
||||
logrus.Panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, v := range NewTestNotifications() {
|
||||
if err := db.Put(ctx, v); err != nil {
|
||||
panic(err)
|
||||
logrus.Panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := db.CreateInstanceAccount(ctx); err != nil {
|
||||
panic(err)
|
||||
logrus.Panic(err)
|
||||
}
|
||||
|
||||
if err := db.CreateInstanceInstance(ctx); err != nil {
|
||||
panic(err)
|
||||
logrus.Panic(err)
|
||||
}
|
||||
|
||||
logrus.Debug("testing db setup complete")
|
||||
}
|
||||
|
||||
// StandardDBTeardown drops all the standard testing tables/models from the database to ensure it's clean for the next test.
|
||||
func StandardDBTeardown(db db.DB) {
|
||||
ctx := context.Background()
|
||||
if db == nil {
|
||||
logrus.Panic("db teardown: db was nil")
|
||||
}
|
||||
for _, m := range testModels {
|
||||
if err := db.DropTable(ctx, m); err != nil {
|
||||
panic(err)
|
||||
logrus.Panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,13 +19,15 @@
|
|||
package testrig
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/router"
|
||||
)
|
||||
|
||||
// NewTestRouter returns a Router suitable for testing
|
||||
func NewTestRouter(db db.DB) router.Router {
|
||||
r, err := router.New(NewTestConfig(), db, NewTestLog())
|
||||
r, err := router.New(context.Background(), NewTestConfig(), db, NewTestLog())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
|
|
|||
18
vendor/github.com/go-pg/pg/v10/.golangci.yml
generated
vendored
18
vendor/github.com/go-pg/pg/v10/.golangci.yml
generated
vendored
|
|
@ -1,18 +0,0 @@
|
|||
run:
|
||||
concurrency: 8
|
||||
deadline: 5m
|
||||
tests: false
|
||||
linters:
|
||||
enable-all: true
|
||||
disable:
|
||||
- gochecknoglobals
|
||||
- gocognit
|
||||
- gomnd
|
||||
- wsl
|
||||
- funlen
|
||||
- godox
|
||||
- goerr113
|
||||
- exhaustive
|
||||
- nestif
|
||||
- gofumpt
|
||||
- goconst
|
||||
4
vendor/github.com/go-pg/pg/v10/.prettierrc
generated
vendored
4
vendor/github.com/go-pg/pg/v10/.prettierrc
generated
vendored
|
|
@ -1,4 +0,0 @@
|
|||
semi: false
|
||||
singleQuote: true
|
||||
proseWrap: always
|
||||
printWidth: 100
|
||||
21
vendor/github.com/go-pg/pg/v10/.travis.yml
generated
vendored
21
vendor/github.com/go-pg/pg/v10/.travis.yml
generated
vendored
|
|
@ -1,21 +0,0 @@
|
|||
dist: xenial
|
||||
language: go
|
||||
|
||||
addons:
|
||||
postgresql: '9.6'
|
||||
|
||||
go:
|
||||
- 1.14.x
|
||||
- 1.15.x
|
||||
- tip
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- go: tip
|
||||
|
||||
go_import_path: github.com/go-pg/pg
|
||||
|
||||
before_install:
|
||||
- psql -U postgres -c "CREATE EXTENSION hstore"
|
||||
- curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s --
|
||||
-b $(go env GOPATH)/bin v1.28.3
|
||||
204
vendor/github.com/go-pg/pg/v10/CHANGELOG.md
generated
vendored
204
vendor/github.com/go-pg/pg/v10/CHANGELOG.md
generated
vendored
|
|
@ -1,204 +0,0 @@
|
|||
# Changelog
|
||||
|
||||
> :heart:
|
||||
> [**Uptrace.dev** - All-in-one tool to optimize performance and monitor errors & logs](https://uptrace.dev)
|
||||
|
||||
**Important**. Please check [Bun](https://bun.uptrace.dev/guide/pg-migration.html) - the next
|
||||
iteration of go-pg built on top of `sql.DB`.
|
||||
|
||||
## v10.10
|
||||
|
||||
- Removed extra OpenTelemetry spans from go-pg core. Now go-pg instrumentation only adds a single
|
||||
span with a SQL query (instead of 4 spans). There are multiple reasons behind this decision:
|
||||
|
||||
- Traces become smaller and less noisy.
|
||||
- [Bun](https://github.com/uptrace/bun) can't support the same level of instrumentation and it is
|
||||
nice to keep the projects synced.
|
||||
- It may be costly to process those 3 extra spans for each query.
|
||||
|
||||
Eventually we hope to replace the information that we no longer collect with OpenTelemetry
|
||||
Metrics.
|
||||
|
||||
## v10.9
|
||||
|
||||
- To make updating easier, extra modules now have the same version as go-pg does. That means that
|
||||
you need to update your imports:
|
||||
|
||||
```
|
||||
github.com/go-pg/pg/extra/pgdebug -> github.com/go-pg/pg/extra/pgdebug/v10
|
||||
github.com/go-pg/pg/extra/pgotel -> github.com/go-pg/pg/extra/pgotel/v10
|
||||
github.com/go-pg/pg/extra/pgsegment -> github.com/go-pg/pg/extra/pgsegment/v10
|
||||
```
|
||||
|
||||
- Exported `pg.Query` which should be used instead of `orm.Query`.
|
||||
- Added `pg.DBI` which is a DB interface implemented by `pg.DB` and `pg.Tx`.
|
||||
|
||||
## v10
|
||||
|
||||
### Resources
|
||||
|
||||
- Docs at https://pg.uptrace.dev/ powered by [mkdocs](https://github.com/squidfunk/mkdocs-material).
|
||||
- [RealWorld example application](https://github.com/uptrace/go-realworld-example-app).
|
||||
- [Discord](https://discord.gg/rWtp5Aj).
|
||||
|
||||
### Features
|
||||
|
||||
- `Select`, `Insert`, and `Update` support `map[string]interface{}`. `Select` also supports
|
||||
`[]map[string]interface{}`.
|
||||
|
||||
```go
|
||||
var mm []map[string]interface{}
|
||||
err := db.Model((*User)(nil)).Limit(10).Select(&mm)
|
||||
```
|
||||
|
||||
- Columns that start with `_` are ignored if there is no destination field.
|
||||
- Optional [faster json encoding](https://github.com/go-pg/pgext).
|
||||
- Added [pgext.OpenTelemetryHook](https://github.com/go-pg/pgext) that adds
|
||||
[OpenTelemetry instrumentation](https://pg.uptrace.dev/tracing/).
|
||||
- Added [pgext.DebugHook](https://github.com/go-pg/pgext) that logs failed queries.
|
||||
- Added `db.Ping` to check if database is healthy.
|
||||
|
||||
### Changes
|
||||
|
||||
- ORM relations are reworked and now require `rel` tag option (but existing code will continue
|
||||
working until v11). Supported options:
|
||||
- `pg:"rel:has-one"` - has one relation.
|
||||
- `pg:"rel:belongs-to"` - belongs to relation.
|
||||
- `pg:"rel:has-many"` - has many relation.
|
||||
- `pg:"many2many:book_genres"` - many to many relation.
|
||||
- Changed `pg.QueryHook` to return temp byte slice to reduce memory usage.
|
||||
- `,msgpack` struct tag marshals data in MessagePack format using
|
||||
https://github.com/vmihailenco/msgpack
|
||||
- Empty slices and maps are no longer marshaled as `NULL`. Nil slices and maps are still marshaled
|
||||
as `NULL`.
|
||||
- Changed `UpdateNotZero` to include zero fields with `pg:",use_zero"` tag. Consider using
|
||||
`Model(*map[string]interface{})` for inserts and updates.
|
||||
- `joinFK` is deprecated in favor of `join_fk`.
|
||||
- `partitionBy` is deprecated in favor of `partition_by`.
|
||||
- ORM shortcuts are removed:
|
||||
- `db.Select(model)` becomes `db.Model(model).WherePK().Select()`.
|
||||
- `db.Insert(model)` becomes `db.Model(model).Insert()`.
|
||||
- `db.Update(model)` becomes `db.Model(model).WherePK().Update()`.
|
||||
- `db.Delete(model)` becomes `db.Model(model).WherePK().Delete()`.
|
||||
- Deprecated types and funcs are removed.
|
||||
- `WhereStruct` is removed.
|
||||
|
||||
## v9
|
||||
|
||||
- `pg:",notnull"` is reworked. Now it means SQL `NOT NULL` constraint and nothing more.
|
||||
- Added `pg:",use_zero"` to prevent go-pg from converting Go zero values to SQL `NULL`.
|
||||
- UpdateNotNull is renamed to UpdateNotZero. As previously it omits zero Go values, but it does not
|
||||
take in account if field is nullable or not.
|
||||
- ORM supports DistinctOn.
|
||||
- Hooks accept and return context.
|
||||
- Client respects Context.Deadline when setting net.Conn deadline.
|
||||
- Client listens on Context.Done while waiting for a connection from the pool and returns an error
|
||||
when context is cancelled.
|
||||
- `Query.Column` does not accept relation name any more. Use `Query.Relation` instead which returns
|
||||
an error if relation does not exist.
|
||||
- urlvalues package is removed in favor of https://github.com/go-pg/urlstruct. You can also use
|
||||
struct based filters via `Query.WhereStruct`.
|
||||
- `NewModel` and `AddModel` methods of `HooklessModel` interface were renamed to `NextColumnScanner`
|
||||
and `AddColumnScanner` respectively.
|
||||
- `types.F` and `pg.F` are deprecated in favor of `pg.Ident`.
|
||||
- `types.Q` is deprecated in favor of `pg.Safe`.
|
||||
- `pg.Q` is deprecated in favor of `pg.SafeQuery`.
|
||||
- `TableName` field is deprecated in favor of `tableName`.
|
||||
- Always use `pg:"..."` struct field tag instead of `sql:"..."`.
|
||||
- `pg:",override"` is deprecated in favor of `pg:",inherit"`.
|
||||
|
||||
## v8
|
||||
|
||||
- Added `QueryContext`, `ExecContext`, and `ModelContext` which accept `context.Context`. Queries
|
||||
are cancelled when context is cancelled.
|
||||
- Model hooks are changed to accept `context.Context` as first argument.
|
||||
- Fixed array and hstore parsers to handle multiple single quotes (#1235).
|
||||
|
||||
## v7
|
||||
|
||||
- DB.OnQueryProcessed is replaced with DB.AddQueryHook.
|
||||
- Added WhereStruct.
|
||||
- orm.Pager is moved to urlvalues.Pager. Pager.FromURLValues returns an error if page or limit
|
||||
params can't be parsed.
|
||||
|
||||
## v6.16
|
||||
|
||||
- Read buffer is re-worked. Default read buffer is increased to 65kb.
|
||||
|
||||
## v6.15
|
||||
|
||||
- Added Options.MinIdleConns.
|
||||
- Options.MaxAge renamed to Options.MaxConnAge.
|
||||
- PoolStats.FreeConns is renamed to PoolStats.IdleConns.
|
||||
- New hook BeforeSelectQuery.
|
||||
- `,override` is renamed to `,inherit`.
|
||||
- Dialer.KeepAlive is set to 5 minutes by default.
|
||||
- Added support "scram-sha-256" authentication.
|
||||
|
||||
## v6.14
|
||||
|
||||
- Fields ignored with `sql:"-"` tag are no longer considered by ORM relation detector.
|
||||
|
||||
## v6.12
|
||||
|
||||
- `Insert`, `Update`, and `Delete` can return `pg.ErrNoRows` and `pg.ErrMultiRows` when `Returning`
|
||||
is used and model expects single row.
|
||||
|
||||
## v6.11
|
||||
|
||||
- `db.Model(&strct).Update()` and `db.Model(&strct).Delete()` no longer adds WHERE condition based
|
||||
on primary key when there are no conditions. Instead you should use `db.Update(&strct)` or
|
||||
`db.Model(&strct).WherePK().Update()`.
|
||||
|
||||
## v6.10
|
||||
|
||||
- `?Columns` is renamed to `?TableColumns`. `?Columns` is changed to produce column names without
|
||||
table alias.
|
||||
|
||||
## v6.9
|
||||
|
||||
- `pg:"fk"` tag now accepts SQL names instead of Go names, e.g. `pg:"fk:ParentId"` becomes
|
||||
`pg:"fk:parent_id"`. Old code should continue working in most cases, but it is strongly advised to
|
||||
start using new convention.
|
||||
- uint and uint64 SQL type is changed from decimal to bigint according to the lesser of two evils
|
||||
principle. Use `sql:"type:decimal"` to get old behavior.
|
||||
|
||||
## v6.8
|
||||
|
||||
- `CreateTable` no longer adds ON DELETE hook by default. To get old behavior users should add
|
||||
`sql:"on_delete:CASCADE"` tag on foreign key field.
|
||||
|
||||
## v6
|
||||
|
||||
- `types.Result` is renamed to `orm.Result`.
|
||||
- Added `OnQueryProcessed` event that can be used to log / report queries timing. Query logger is
|
||||
removed.
|
||||
- `orm.URLValues` is renamed to `orm.URLFilters`. It no longer adds ORDER clause.
|
||||
- `orm.Pager` is renamed to `orm.Pagination`.
|
||||
- Support for net.IP and net.IPNet.
|
||||
- Support for context.Context.
|
||||
- Bulk/multi updates.
|
||||
- Query.WhereGroup for enclosing conditions in parentheses.
|
||||
|
||||
## v5
|
||||
|
||||
- All fields are nullable by default. `,null` tag is replaced with `,notnull`.
|
||||
- `Result.Affected` renamed to `Result.RowsAffected`.
|
||||
- Added `Result.RowsReturned`.
|
||||
- `Create` renamed to `Insert`, `BeforeCreate` to `BeforeInsert`, `AfterCreate` to `AfterInsert`.
|
||||
- Indexed placeholders support, e.g. `db.Exec("SELECT ?0 + ?0", 1)`.
|
||||
- Named placeholders are evaluated when query is executed.
|
||||
- Added Update and Delete hooks.
|
||||
- Order reworked to quote column names. OrderExpr added to bypass Order quoting restrictions.
|
||||
- Group reworked to quote column names. GroupExpr added to bypass Group quoting restrictions.
|
||||
|
||||
## v4
|
||||
|
||||
- `Options.Host` and `Options.Port` merged into `Options.Addr`.
|
||||
- Added `Options.MaxRetries`. Now queries are not retried by default.
|
||||
- `LoadInto` renamed to `Scan`, `ColumnLoader` renamed to `ColumnScanner`, LoadColumn renamed to
|
||||
ScanColumn, `NewRecord() interface{}` changed to `NewModel() ColumnScanner`,
|
||||
`AppendQuery(dst []byte) []byte` changed to `AppendValue(dst []byte, quote bool) ([]byte, error)`.
|
||||
- Structs, maps and slices are marshalled to JSON by default.
|
||||
- Added support for scanning slices, .e.g. scanning `[]int`.
|
||||
- Added object relational mapping.
|
||||
24
vendor/github.com/go-pg/pg/v10/LICENSE
generated
vendored
24
vendor/github.com/go-pg/pg/v10/LICENSE
generated
vendored
|
|
@ -1,24 +0,0 @@
|
|||
Copyright (c) 2013 github.com/go-pg/pg Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
27
vendor/github.com/go-pg/pg/v10/Makefile
generated
vendored
27
vendor/github.com/go-pg/pg/v10/Makefile
generated
vendored
|
|
@ -1,27 +0,0 @@
|
|||
all:
|
||||
TZ= go test ./...
|
||||
TZ= go test ./... -short -race
|
||||
TZ= go test ./... -run=NONE -bench=. -benchmem
|
||||
env GOOS=linux GOARCH=386 go test ./...
|
||||
go vet
|
||||
golangci-lint run
|
||||
|
||||
.PHONY: cleanTest
|
||||
cleanTest:
|
||||
docker rm -fv pg || true
|
||||
|
||||
.PHONY: pre-test
|
||||
pre-test: cleanTest
|
||||
docker run -d --name pg -p 5432:5432 -e POSTGRES_HOST_AUTH_METHOD=trust postgres:9.6
|
||||
sleep 10
|
||||
docker exec pg psql -U postgres -c "CREATE EXTENSION hstore"
|
||||
|
||||
.PHONY: test
|
||||
test: pre-test
|
||||
TZ= PGSSLMODE=disable go test ./... -v
|
||||
|
||||
tag:
|
||||
git tag $(VERSION)
|
||||
git tag extra/pgdebug/$(VERSION)
|
||||
git tag extra/pgotel/$(VERSION)
|
||||
git tag extra/pgsegment/$(VERSION)
|
||||
240
vendor/github.com/go-pg/pg/v10/README.md
generated
vendored
240
vendor/github.com/go-pg/pg/v10/README.md
generated
vendored
|
|
@ -1,240 +0,0 @@
|
|||
<p align="center">
|
||||
<a href="https://uptrace.dev/?utm_source=gh-pg&utm_campaign=gh-pg-banner1">
|
||||
<img src="https://raw.githubusercontent.com/uptrace/roadmap/master/banner1.png">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
# PostgreSQL client and ORM for Golang
|
||||
|
||||
[](https://travis-ci.org/go-pg/pg)
|
||||
[](https://pkg.go.dev/github.com/go-pg/pg/v10)
|
||||
[](https://pg.uptrace.dev/)
|
||||
[](https://discord.gg/rWtp5Aj)
|
||||
|
||||
**Important**. Please check [Bun](https://bun.uptrace.dev/guide/pg-migration.html) - the next
|
||||
iteration of go-pg built on top of `sql.DB`.
|
||||
|
||||
- Join [Discord](https://discord.gg/rWtp5Aj) to ask questions.
|
||||
- [Documentation](https://pg.uptrace.dev)
|
||||
- [Reference](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc)
|
||||
- [Examples](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#pkg-examples)
|
||||
- Example projects:
|
||||
- [treemux](https://github.com/uptrace/go-treemux-realworld-example-app)
|
||||
- [gin](https://github.com/gogjango/gjango)
|
||||
- [go-kit](https://github.com/Tsovak/rest-api-demo)
|
||||
- [aah framework](https://github.com/kieusonlam/golamapi)
|
||||
- [GraphQL Tutorial on YouTube](https://www.youtube.com/playlist?list=PLzQWIQOqeUSNwXcneWYJHUREAIucJ5UZn).
|
||||
|
||||
## Ecosystem
|
||||
|
||||
- Migrations by [vmihailenco](https://github.com/go-pg/migrations) and
|
||||
[robinjoseph08](https://github.com/robinjoseph08/go-pg-migrations).
|
||||
- [Genna - cli tool for generating go-pg models](https://github.com/dizzyfool/genna).
|
||||
- [bigint](https://github.com/d-fal/bigint) - big.Int type for go-pg.
|
||||
- [urlstruct](https://github.com/go-pg/urlstruct) to decode `url.Values` into structs.
|
||||
- [Sharding](https://github.com/go-pg/sharding).
|
||||
- [go-pg-monitor](https://github.com/hypnoglow/go-pg-monitor) - Prometheus metrics based on go-pg
|
||||
client stats.
|
||||
|
||||
## Features
|
||||
|
||||
- Basic types: integers, floats, string, bool, time.Time, net.IP, net.IPNet.
|
||||
- sql.NullBool, sql.NullString, sql.NullInt64, sql.NullFloat64 and
|
||||
[pg.NullTime](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#NullTime).
|
||||
- [sql.Scanner](http://golang.org/pkg/database/sql/#Scanner) and
|
||||
[sql/driver.Valuer](http://golang.org/pkg/database/sql/driver/#Valuer) interfaces.
|
||||
- Structs, maps and arrays are marshalled as JSON by default.
|
||||
- PostgreSQL multidimensional Arrays using
|
||||
[array tag](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB-Model-PostgresArrayStructTag)
|
||||
and [Array wrapper](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-Array).
|
||||
- Hstore using
|
||||
[hstore tag](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB-Model-HstoreStructTag)
|
||||
and [Hstore wrapper](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-Hstore).
|
||||
- [Composite types](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB-Model-CompositeType).
|
||||
- All struct fields are nullable by default and zero values (empty string, 0, zero time, empty map
|
||||
or slice, nil ptr) are marshalled as SQL `NULL`. `pg:",notnull"` is used to add SQL `NOT NULL`
|
||||
constraint and `pg:",use_zero"` to allow Go zero values.
|
||||
- [Transactions](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB-Begin).
|
||||
- [Prepared statements](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB-Prepare).
|
||||
- [Notifications](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-Listener) using
|
||||
`LISTEN` and `NOTIFY`.
|
||||
- [Copying data](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB-CopyFrom) using
|
||||
`COPY FROM` and `COPY TO`.
|
||||
- [Timeouts](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#Options) and canceling queries using
|
||||
context.Context.
|
||||
- Automatic connection pooling with
|
||||
[circuit breaker](https://en.wikipedia.org/wiki/Circuit_breaker_design_pattern) support.
|
||||
- Queries retry on network errors.
|
||||
- Working with models using
|
||||
[ORM](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB.Model) and
|
||||
[SQL](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB.Query).
|
||||
- Scanning variables using
|
||||
[ORM](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB.Model-SelectSomeColumnsIntoVars)
|
||||
and [SQL](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-Scan).
|
||||
- [SelectOrInsert](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB.Model-InsertSelectOrInsert)
|
||||
using on-conflict.
|
||||
- [INSERT ... ON CONFLICT DO UPDATE](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB.Model-InsertOnConflictDoUpdate)
|
||||
using ORM.
|
||||
- Bulk/batch
|
||||
[inserts](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB.Model-BulkInsert),
|
||||
[updates](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB.Model-BulkUpdate), and
|
||||
[deletes](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB.Model-BulkDelete).
|
||||
- Common table expressions using
|
||||
[WITH](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB.Model-SelectWith) and
|
||||
[WrapWith](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB.Model-SelectWrapWith).
|
||||
- [CountEstimate](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB.Model-CountEstimate)
|
||||
using `EXPLAIN` to get
|
||||
[estimated number of matching rows](https://wiki.postgresql.org/wiki/Count_estimate).
|
||||
- ORM supports
|
||||
[has one](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB.Model-HasOne),
|
||||
[belongs to](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB.Model-BelongsTo),
|
||||
[has many](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB.Model-HasMany), and
|
||||
[many to many](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB.Model-ManyToMany)
|
||||
with composite/multi-column primary keys.
|
||||
- [Soft deletes](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB.Model-SoftDelete).
|
||||
- [Creating tables from structs](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB.Model-CreateTable).
|
||||
- [ForEach](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB.Model-ForEach) that calls
|
||||
a function for each row returned by the query without loading all rows into the memory.
|
||||
|
||||
## Installation
|
||||
|
||||
go-pg supports 2 last Go versions and requires a Go version with
|
||||
[modules](https://github.com/golang/go/wiki/Modules) support. So make sure to initialize a Go
|
||||
module:
|
||||
|
||||
```shell
|
||||
go mod init github.com/my/repo
|
||||
```
|
||||
|
||||
And then install go-pg (note _v10_ in the import; omitting it is a popular mistake):
|
||||
|
||||
```shell
|
||||
go get github.com/go-pg/pg/v10
|
||||
```
|
||||
|
||||
## Quickstart
|
||||
|
||||
```go
|
||||
package pg_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/go-pg/pg/v10"
|
||||
"github.com/go-pg/pg/v10/orm"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
Id int64
|
||||
Name string
|
||||
Emails []string
|
||||
}
|
||||
|
||||
func (u User) String() string {
|
||||
return fmt.Sprintf("User<%d %s %v>", u.Id, u.Name, u.Emails)
|
||||
}
|
||||
|
||||
type Story struct {
|
||||
Id int64
|
||||
Title string
|
||||
AuthorId int64
|
||||
Author *User `pg:"rel:has-one"`
|
||||
}
|
||||
|
||||
func (s Story) String() string {
|
||||
return fmt.Sprintf("Story<%d %s %s>", s.Id, s.Title, s.Author)
|
||||
}
|
||||
|
||||
func ExampleDB_Model() {
|
||||
db := pg.Connect(&pg.Options{
|
||||
User: "postgres",
|
||||
})
|
||||
defer db.Close()
|
||||
|
||||
err := createSchema(db)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
user1 := &User{
|
||||
Name: "admin",
|
||||
Emails: []string{"admin1@admin", "admin2@admin"},
|
||||
}
|
||||
_, err = db.Model(user1).Insert()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
_, err = db.Model(&User{
|
||||
Name: "root",
|
||||
Emails: []string{"root1@root", "root2@root"},
|
||||
}).Insert()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
story1 := &Story{
|
||||
Title: "Cool story",
|
||||
AuthorId: user1.Id,
|
||||
}
|
||||
_, err = db.Model(story1).Insert()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Select user by primary key.
|
||||
user := &User{Id: user1.Id}
|
||||
err = db.Model(user).WherePK().Select()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Select all users.
|
||||
var users []User
|
||||
err = db.Model(&users).Select()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Select story and associated author in one query.
|
||||
story := new(Story)
|
||||
err = db.Model(story).
|
||||
Relation("Author").
|
||||
Where("story.id = ?", story1.Id).
|
||||
Select()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Println(user)
|
||||
fmt.Println(users)
|
||||
fmt.Println(story)
|
||||
// Output: User<1 admin [admin1@admin admin2@admin]>
|
||||
// [User<1 admin [admin1@admin admin2@admin]> User<2 root [root1@root root2@root]>]
|
||||
// Story<1 Cool story User<1 admin [admin1@admin admin2@admin]>>
|
||||
}
|
||||
|
||||
// createSchema creates database schema for User and Story models.
|
||||
func createSchema(db *pg.DB) error {
|
||||
models := []interface{}{
|
||||
(*User)(nil),
|
||||
(*Story)(nil),
|
||||
}
|
||||
|
||||
for _, model := range models {
|
||||
err := db.Model(model).CreateTable(&orm.CreateTableOptions{
|
||||
Temp: true,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Fast and flexible HTTP router](https://github.com/vmihailenco/treemux)
|
||||
- [Golang msgpack](https://github.com/vmihailenco/msgpack)
|
||||
- [Golang message task queue](https://github.com/vmihailenco/taskq)
|
||||
618
vendor/github.com/go-pg/pg/v10/base.go
generated
vendored
618
vendor/github.com/go-pg/pg/v10/base.go
generated
vendored
|
|
@ -1,618 +0,0 @@
|
|||
package pg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/go-pg/pg/v10/internal"
|
||||
"github.com/go-pg/pg/v10/internal/pool"
|
||||
"github.com/go-pg/pg/v10/orm"
|
||||
"github.com/go-pg/pg/v10/types"
|
||||
)
|
||||
|
||||
type baseDB struct {
|
||||
db orm.DB
|
||||
opt *Options
|
||||
pool pool.Pooler
|
||||
|
||||
fmter *orm.Formatter
|
||||
queryHooks []QueryHook
|
||||
}
|
||||
|
||||
// PoolStats contains the stats of a connection pool.
|
||||
type PoolStats pool.Stats
|
||||
|
||||
// PoolStats returns connection pool stats.
|
||||
func (db *baseDB) PoolStats() *PoolStats {
|
||||
stats := db.pool.Stats()
|
||||
return (*PoolStats)(stats)
|
||||
}
|
||||
|
||||
func (db *baseDB) clone() *baseDB {
|
||||
return &baseDB{
|
||||
db: db.db,
|
||||
opt: db.opt,
|
||||
pool: db.pool,
|
||||
|
||||
fmter: db.fmter,
|
||||
queryHooks: copyQueryHooks(db.queryHooks),
|
||||
}
|
||||
}
|
||||
|
||||
func (db *baseDB) withPool(p pool.Pooler) *baseDB {
|
||||
cp := db.clone()
|
||||
cp.pool = p
|
||||
return cp
|
||||
}
|
||||
|
||||
func (db *baseDB) WithTimeout(d time.Duration) *baseDB {
|
||||
newopt := *db.opt
|
||||
newopt.ReadTimeout = d
|
||||
newopt.WriteTimeout = d
|
||||
|
||||
cp := db.clone()
|
||||
cp.opt = &newopt
|
||||
return cp
|
||||
}
|
||||
|
||||
func (db *baseDB) WithParam(param string, value interface{}) *baseDB {
|
||||
cp := db.clone()
|
||||
cp.fmter = db.fmter.WithParam(param, value)
|
||||
return cp
|
||||
}
|
||||
|
||||
// Param returns value for the param.
|
||||
func (db *baseDB) Param(param string) interface{} {
|
||||
return db.fmter.Param(param)
|
||||
}
|
||||
|
||||
func (db *baseDB) retryBackoff(retry int) time.Duration {
|
||||
return internal.RetryBackoff(retry, db.opt.MinRetryBackoff, db.opt.MaxRetryBackoff)
|
||||
}
|
||||
|
||||
func (db *baseDB) getConn(ctx context.Context) (*pool.Conn, error) {
|
||||
cn, err := db.pool.Get(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if cn.Inited {
|
||||
return cn, nil
|
||||
}
|
||||
|
||||
if err := db.initConn(ctx, cn); err != nil {
|
||||
db.pool.Remove(ctx, cn, err)
|
||||
// It is safe to reset StickyConnPool if conn can't be initialized.
|
||||
if p, ok := db.pool.(*pool.StickyConnPool); ok {
|
||||
_ = p.Reset(ctx)
|
||||
}
|
||||
if err := internal.Unwrap(err); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return cn, nil
|
||||
}
|
||||
|
||||
func (db *baseDB) initConn(ctx context.Context, cn *pool.Conn) error {
|
||||
if cn.Inited {
|
||||
return nil
|
||||
}
|
||||
cn.Inited = true
|
||||
|
||||
if db.opt.TLSConfig != nil {
|
||||
err := db.enableSSL(ctx, cn, db.opt.TLSConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err := db.startup(ctx, cn, db.opt.User, db.opt.Password, db.opt.Database, db.opt.ApplicationName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if db.opt.OnConnect != nil {
|
||||
p := pool.NewSingleConnPool(db.pool, cn)
|
||||
return db.opt.OnConnect(ctx, newConn(ctx, db.withPool(p)))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *baseDB) releaseConn(ctx context.Context, cn *pool.Conn, err error) {
|
||||
if isBadConn(err, false) {
|
||||
db.pool.Remove(ctx, cn, err)
|
||||
} else {
|
||||
db.pool.Put(ctx, cn)
|
||||
}
|
||||
}
|
||||
|
||||
func (db *baseDB) withConn(
|
||||
ctx context.Context, fn func(context.Context, *pool.Conn) error,
|
||||
) error {
|
||||
cn, err := db.getConn(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var fnDone chan struct{}
|
||||
if ctx != nil && ctx.Done() != nil {
|
||||
fnDone = make(chan struct{})
|
||||
go func() {
|
||||
select {
|
||||
case <-fnDone: // fn has finished, skip cancel
|
||||
case <-ctx.Done():
|
||||
err := db.cancelRequest(cn.ProcessID, cn.SecretKey)
|
||||
if err != nil {
|
||||
internal.Logger.Printf(ctx, "cancelRequest failed: %s", err)
|
||||
}
|
||||
// Signal end of conn use.
|
||||
fnDone <- struct{}{}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if fnDone == nil {
|
||||
db.releaseConn(ctx, cn, err)
|
||||
return
|
||||
}
|
||||
|
||||
select {
|
||||
case <-fnDone: // wait for cancel to finish request
|
||||
// Looks like the canceled connection must be always removed from the pool.
|
||||
db.pool.Remove(ctx, cn, err)
|
||||
case fnDone <- struct{}{}: // signal fn finish, skip cancel goroutine
|
||||
db.releaseConn(ctx, cn, err)
|
||||
}
|
||||
}()
|
||||
|
||||
err = fn(ctx, cn)
|
||||
return err
|
||||
}
|
||||
|
||||
func (db *baseDB) shouldRetry(err error) bool {
|
||||
switch err {
|
||||
case io.EOF, io.ErrUnexpectedEOF:
|
||||
return true
|
||||
case nil, context.Canceled, context.DeadlineExceeded:
|
||||
return false
|
||||
}
|
||||
|
||||
if pgerr, ok := err.(Error); ok {
|
||||
switch pgerr.Field('C') {
|
||||
case "40001", // serialization_failure
|
||||
"53300", // too_many_connections
|
||||
"55000": // attempted to delete invisible tuple
|
||||
return true
|
||||
case "57014": // statement_timeout
|
||||
return db.opt.RetryStatementTimeout
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if _, ok := err.(timeoutError); ok {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// Close closes the database client, releasing any open resources.
|
||||
//
|
||||
// It is rare to Close a DB, as the DB handle is meant to be
|
||||
// long-lived and shared between many goroutines.
|
||||
func (db *baseDB) Close() error {
|
||||
return db.pool.Close()
|
||||
}
|
||||
|
||||
// Exec executes a query ignoring returned rows. The params are for any
|
||||
// placeholders in the query.
|
||||
func (db *baseDB) Exec(query interface{}, params ...interface{}) (res Result, err error) {
|
||||
return db.exec(db.db.Context(), query, params...)
|
||||
}
|
||||
|
||||
func (db *baseDB) ExecContext(c context.Context, query interface{}, params ...interface{}) (Result, error) {
|
||||
return db.exec(c, query, params...)
|
||||
}
|
||||
|
||||
func (db *baseDB) exec(ctx context.Context, query interface{}, params ...interface{}) (Result, error) {
|
||||
wb := pool.GetWriteBuffer()
|
||||
defer pool.PutWriteBuffer(wb)
|
||||
|
||||
if err := writeQueryMsg(wb, db.fmter, query, params...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, evt, err := db.beforeQuery(ctx, db.db, nil, query, params, wb.Query())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var res Result
|
||||
var lastErr error
|
||||
for attempt := 0; attempt <= db.opt.MaxRetries; attempt++ {
|
||||
if attempt > 0 {
|
||||
if err := internal.Sleep(ctx, db.retryBackoff(attempt-1)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
lastErr = db.withConn(ctx, func(ctx context.Context, cn *pool.Conn) error {
|
||||
res, err = db.simpleQuery(ctx, cn, wb)
|
||||
return err
|
||||
})
|
||||
if !db.shouldRetry(lastErr) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if err := db.afterQuery(ctx, evt, res, lastErr); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, lastErr
|
||||
}
|
||||
|
||||
// ExecOne acts like Exec, but query must affect only one row. It
|
||||
// returns ErrNoRows error when query returns zero rows or
|
||||
// ErrMultiRows when query returns multiple rows.
|
||||
func (db *baseDB) ExecOne(query interface{}, params ...interface{}) (Result, error) {
|
||||
return db.execOne(db.db.Context(), query, params...)
|
||||
}
|
||||
|
||||
func (db *baseDB) ExecOneContext(ctx context.Context, query interface{}, params ...interface{}) (Result, error) {
|
||||
return db.execOne(ctx, query, params...)
|
||||
}
|
||||
|
||||
func (db *baseDB) execOne(c context.Context, query interface{}, params ...interface{}) (Result, error) {
|
||||
res, err := db.ExecContext(c, query, params...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := internal.AssertOneRow(res.RowsAffected()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Query executes a query that returns rows, typically a SELECT.
|
||||
// The params are for any placeholders in the query.
|
||||
func (db *baseDB) Query(model, query interface{}, params ...interface{}) (res Result, err error) {
|
||||
return db.query(db.db.Context(), model, query, params...)
|
||||
}
|
||||
|
||||
func (db *baseDB) QueryContext(c context.Context, model, query interface{}, params ...interface{}) (Result, error) {
|
||||
return db.query(c, model, query, params...)
|
||||
}
|
||||
|
||||
func (db *baseDB) query(ctx context.Context, model, query interface{}, params ...interface{}) (Result, error) {
|
||||
wb := pool.GetWriteBuffer()
|
||||
defer pool.PutWriteBuffer(wb)
|
||||
|
||||
if err := writeQueryMsg(wb, db.fmter, query, params...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, evt, err := db.beforeQuery(ctx, db.db, model, query, params, wb.Query())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var res Result
|
||||
var lastErr error
|
||||
for attempt := 0; attempt <= db.opt.MaxRetries; attempt++ {
|
||||
if attempt > 0 {
|
||||
if err := internal.Sleep(ctx, db.retryBackoff(attempt-1)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
lastErr = db.withConn(ctx, func(ctx context.Context, cn *pool.Conn) error {
|
||||
res, err = db.simpleQueryData(ctx, cn, model, wb)
|
||||
return err
|
||||
})
|
||||
if !db.shouldRetry(lastErr) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if err := db.afterQuery(ctx, evt, res, lastErr); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, lastErr
|
||||
}
|
||||
|
||||
// QueryOne acts like Query, but query must return only one row. It
|
||||
// returns ErrNoRows error when query returns zero rows or
|
||||
// ErrMultiRows when query returns multiple rows.
|
||||
func (db *baseDB) QueryOne(model, query interface{}, params ...interface{}) (Result, error) {
|
||||
return db.queryOne(db.db.Context(), model, query, params...)
|
||||
}
|
||||
|
||||
func (db *baseDB) QueryOneContext(
|
||||
ctx context.Context, model, query interface{}, params ...interface{},
|
||||
) (Result, error) {
|
||||
return db.queryOne(ctx, model, query, params...)
|
||||
}
|
||||
|
||||
func (db *baseDB) queryOne(ctx context.Context, model, query interface{}, params ...interface{}) (Result, error) {
|
||||
res, err := db.QueryContext(ctx, model, query, params...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := internal.AssertOneRow(res.RowsAffected()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// CopyFrom copies data from reader to a table.
|
||||
func (db *baseDB) CopyFrom(r io.Reader, query interface{}, params ...interface{}) (res Result, err error) {
|
||||
c := db.db.Context()
|
||||
err = db.withConn(c, func(c context.Context, cn *pool.Conn) error {
|
||||
res, err = db.copyFrom(c, cn, r, query, params...)
|
||||
return err
|
||||
})
|
||||
return res, err
|
||||
}
|
||||
|
||||
// TODO: don't get/put conn in the pool.
|
||||
func (db *baseDB) copyFrom(
|
||||
ctx context.Context, cn *pool.Conn, r io.Reader, query interface{}, params ...interface{},
|
||||
) (res Result, err error) {
|
||||
var evt *QueryEvent
|
||||
|
||||
wb := pool.GetWriteBuffer()
|
||||
defer pool.PutWriteBuffer(wb)
|
||||
|
||||
if err := writeQueryMsg(wb, db.fmter, query, params...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var model interface{}
|
||||
if len(params) > 0 {
|
||||
model, _ = params[len(params)-1].(orm.TableModel)
|
||||
}
|
||||
|
||||
ctx, evt, err = db.beforeQuery(ctx, db.db, model, query, params, wb.Query())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Note that afterQuery uses the err.
|
||||
defer func() {
|
||||
if afterQueryErr := db.afterQuery(ctx, evt, res, err); afterQueryErr != nil {
|
||||
err = afterQueryErr
|
||||
}
|
||||
}()
|
||||
|
||||
err = cn.WithWriter(ctx, db.opt.WriteTimeout, func(wb *pool.WriteBuffer) error {
|
||||
return writeQueryMsg(wb, db.fmter, query, params...)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = cn.WithReader(ctx, db.opt.ReadTimeout, readCopyInResponse)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for {
|
||||
err = cn.WithWriter(ctx, db.opt.WriteTimeout, func(wb *pool.WriteBuffer) error {
|
||||
return writeCopyData(wb, r)
|
||||
})
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
err = cn.WithWriter(ctx, db.opt.WriteTimeout, func(wb *pool.WriteBuffer) error {
|
||||
writeCopyDone(wb)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = cn.WithReader(ctx, db.opt.ReadTimeout, func(rd *pool.ReaderContext) error {
|
||||
res, err = readReadyForQuery(rd)
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// CopyTo copies data from a table to writer.
|
||||
func (db *baseDB) CopyTo(w io.Writer, query interface{}, params ...interface{}) (res Result, err error) {
|
||||
c := db.db.Context()
|
||||
err = db.withConn(c, func(c context.Context, cn *pool.Conn) error {
|
||||
res, err = db.copyTo(c, cn, w, query, params...)
|
||||
return err
|
||||
})
|
||||
return res, err
|
||||
}
|
||||
|
||||
func (db *baseDB) copyTo(
|
||||
ctx context.Context, cn *pool.Conn, w io.Writer, query interface{}, params ...interface{},
|
||||
) (res Result, err error) {
|
||||
var evt *QueryEvent
|
||||
|
||||
wb := pool.GetWriteBuffer()
|
||||
defer pool.PutWriteBuffer(wb)
|
||||
|
||||
if err := writeQueryMsg(wb, db.fmter, query, params...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var model interface{}
|
||||
if len(params) > 0 {
|
||||
model, _ = params[len(params)-1].(orm.TableModel)
|
||||
}
|
||||
|
||||
ctx, evt, err = db.beforeQuery(ctx, db.db, model, query, params, wb.Query())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Note that afterQuery uses the err.
|
||||
defer func() {
|
||||
if afterQueryErr := db.afterQuery(ctx, evt, res, err); afterQueryErr != nil {
|
||||
err = afterQueryErr
|
||||
}
|
||||
}()
|
||||
|
||||
err = cn.WithWriter(ctx, db.opt.WriteTimeout, func(wb *pool.WriteBuffer) error {
|
||||
return writeQueryMsg(wb, db.fmter, query, params...)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = cn.WithReader(ctx, db.opt.ReadTimeout, func(rd *pool.ReaderContext) error {
|
||||
err := readCopyOutResponse(rd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res, err = readCopyData(rd, w)
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Ping verifies a connection to the database is still alive,
|
||||
// establishing a connection if necessary.
|
||||
func (db *baseDB) Ping(ctx context.Context) error {
|
||||
_, err := db.ExecContext(ctx, "SELECT 1")
|
||||
return err
|
||||
}
|
||||
|
||||
// Model returns new query for the model.
|
||||
func (db *baseDB) Model(model ...interface{}) *Query {
|
||||
return orm.NewQuery(db.db, model...)
|
||||
}
|
||||
|
||||
func (db *baseDB) ModelContext(c context.Context, model ...interface{}) *Query {
|
||||
return orm.NewQueryContext(c, db.db, model...)
|
||||
}
|
||||
|
||||
func (db *baseDB) Formatter() orm.QueryFormatter {
|
||||
return db.fmter
|
||||
}
|
||||
|
||||
func (db *baseDB) cancelRequest(processID, secretKey int32) error {
|
||||
c := context.TODO()
|
||||
|
||||
cn, err := db.pool.NewConn(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
_ = db.pool.CloseConn(cn)
|
||||
}()
|
||||
|
||||
return cn.WithWriter(c, db.opt.WriteTimeout, func(wb *pool.WriteBuffer) error {
|
||||
writeCancelRequestMsg(wb, processID, secretKey)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (db *baseDB) simpleQuery(
|
||||
c context.Context, cn *pool.Conn, wb *pool.WriteBuffer,
|
||||
) (*result, error) {
|
||||
if err := cn.WriteBuffer(c, db.opt.WriteTimeout, wb); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var res *result
|
||||
if err := cn.WithReader(c, db.opt.ReadTimeout, func(rd *pool.ReaderContext) error {
|
||||
var err error
|
||||
res, err = readSimpleQuery(rd)
|
||||
return err
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (db *baseDB) simpleQueryData(
|
||||
c context.Context, cn *pool.Conn, model interface{}, wb *pool.WriteBuffer,
|
||||
) (*result, error) {
|
||||
if err := cn.WriteBuffer(c, db.opt.WriteTimeout, wb); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var res *result
|
||||
if err := cn.WithReader(c, db.opt.ReadTimeout, func(rd *pool.ReaderContext) error {
|
||||
var err error
|
||||
res, err = readSimpleQueryData(c, rd, model)
|
||||
return err
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Prepare creates a prepared statement for later queries or
|
||||
// executions. Multiple queries or executions may be run concurrently
|
||||
// from the returned statement.
|
||||
func (db *baseDB) Prepare(q string) (*Stmt, error) {
|
||||
return prepareStmt(db.withPool(pool.NewStickyConnPool(db.pool)), q)
|
||||
}
|
||||
|
||||
func (db *baseDB) prepare(
|
||||
c context.Context, cn *pool.Conn, q string,
|
||||
) (string, []types.ColumnInfo, error) {
|
||||
name := cn.NextID()
|
||||
err := cn.WithWriter(c, db.opt.WriteTimeout, func(wb *pool.WriteBuffer) error {
|
||||
writeParseDescribeSyncMsg(wb, name, q)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
var columns []types.ColumnInfo
|
||||
err = cn.WithReader(c, db.opt.ReadTimeout, func(rd *pool.ReaderContext) error {
|
||||
columns, err = readParseDescribeSync(rd)
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
return name, columns, nil
|
||||
}
|
||||
|
||||
func (db *baseDB) closeStmt(c context.Context, cn *pool.Conn, name string) error {
|
||||
err := cn.WithWriter(c, db.opt.WriteTimeout, func(wb *pool.WriteBuffer) error {
|
||||
writeCloseMsg(wb, name)
|
||||
writeFlushMsg(wb)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = cn.WithReader(c, db.opt.ReadTimeout, readCloseCompleteMsg)
|
||||
return err
|
||||
}
|
||||
142
vendor/github.com/go-pg/pg/v10/db.go
generated
vendored
142
vendor/github.com/go-pg/pg/v10/db.go
generated
vendored
|
|
@ -1,142 +0,0 @@
|
|||
package pg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/go-pg/pg/v10/internal/pool"
|
||||
"github.com/go-pg/pg/v10/orm"
|
||||
)
|
||||
|
||||
// Connect connects to a database using provided options.
|
||||
//
|
||||
// The returned DB is safe for concurrent use by multiple goroutines
|
||||
// and maintains its own connection pool.
|
||||
func Connect(opt *Options) *DB {
|
||||
opt.init()
|
||||
return newDB(
|
||||
context.Background(),
|
||||
&baseDB{
|
||||
opt: opt,
|
||||
pool: newConnPool(opt),
|
||||
fmter: orm.NewFormatter(),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func newDB(ctx context.Context, baseDB *baseDB) *DB {
|
||||
db := &DB{
|
||||
baseDB: baseDB.clone(),
|
||||
ctx: ctx,
|
||||
}
|
||||
db.baseDB.db = db
|
||||
return db
|
||||
}
|
||||
|
||||
// DB is a database handle representing a pool of zero or more
|
||||
// underlying connections. It's safe for concurrent use by multiple
|
||||
// goroutines.
|
||||
type DB struct {
|
||||
*baseDB
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
var _ orm.DB = (*DB)(nil)
|
||||
|
||||
func (db *DB) String() string {
|
||||
return fmt.Sprintf("DB<Addr=%q%s>", db.opt.Addr, db.fmter)
|
||||
}
|
||||
|
||||
// Options returns read-only Options that were used to connect to the DB.
|
||||
func (db *DB) Options() *Options {
|
||||
return db.opt
|
||||
}
|
||||
|
||||
// Context returns DB context.
|
||||
func (db *DB) Context() context.Context {
|
||||
return db.ctx
|
||||
}
|
||||
|
||||
// WithContext returns a copy of the DB that uses the ctx.
|
||||
func (db *DB) WithContext(ctx context.Context) *DB {
|
||||
return newDB(ctx, db.baseDB)
|
||||
}
|
||||
|
||||
// WithTimeout returns a copy of the DB that uses d as the read/write timeout.
|
||||
func (db *DB) WithTimeout(d time.Duration) *DB {
|
||||
return newDB(db.ctx, db.baseDB.WithTimeout(d))
|
||||
}
|
||||
|
||||
// WithParam returns a copy of the DB that replaces the param with the value
|
||||
// in queries.
|
||||
func (db *DB) WithParam(param string, value interface{}) *DB {
|
||||
return newDB(db.ctx, db.baseDB.WithParam(param, value))
|
||||
}
|
||||
|
||||
// Listen listens for notifications sent with NOTIFY command.
|
||||
func (db *DB) Listen(ctx context.Context, channels ...string) *Listener {
|
||||
ln := &Listener{
|
||||
db: db,
|
||||
}
|
||||
ln.init()
|
||||
_ = ln.Listen(ctx, channels...)
|
||||
return ln
|
||||
}
|
||||
|
||||
// Conn represents a single database connection rather than a pool of database
|
||||
// connections. Prefer running queries from DB unless there is a specific
|
||||
// need for a continuous single database connection.
|
||||
//
|
||||
// A Conn must call Close to return the connection to the database pool
|
||||
// and may do so concurrently with a running query.
|
||||
//
|
||||
// After a call to Close, all operations on the connection fail.
|
||||
type Conn struct {
|
||||
*baseDB
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
var _ orm.DB = (*Conn)(nil)
|
||||
|
||||
// Conn returns a single connection from the connection pool.
|
||||
// Queries run on the same Conn will be run in the same database session.
|
||||
//
|
||||
// Every Conn must be returned to the database pool after use by
|
||||
// calling Conn.Close.
|
||||
func (db *DB) Conn() *Conn {
|
||||
return newConn(db.ctx, db.baseDB.withPool(pool.NewStickyConnPool(db.pool)))
|
||||
}
|
||||
|
||||
func newConn(ctx context.Context, baseDB *baseDB) *Conn {
|
||||
conn := &Conn{
|
||||
baseDB: baseDB,
|
||||
ctx: ctx,
|
||||
}
|
||||
conn.baseDB.db = conn
|
||||
return conn
|
||||
}
|
||||
|
||||
// Context returns DB context.
|
||||
func (db *Conn) Context() context.Context {
|
||||
if db.ctx != nil {
|
||||
return db.ctx
|
||||
}
|
||||
return context.Background()
|
||||
}
|
||||
|
||||
// WithContext returns a copy of the DB that uses the ctx.
|
||||
func (db *Conn) WithContext(ctx context.Context) *Conn {
|
||||
return newConn(ctx, db.baseDB)
|
||||
}
|
||||
|
||||
// WithTimeout returns a copy of the DB that uses d as the read/write timeout.
|
||||
func (db *Conn) WithTimeout(d time.Duration) *Conn {
|
||||
return newConn(db.ctx, db.baseDB.WithTimeout(d))
|
||||
}
|
||||
|
||||
// WithParam returns a copy of the DB that replaces the param with the value
|
||||
// in queries.
|
||||
func (db *Conn) WithParam(param string, value interface{}) *Conn {
|
||||
return newConn(db.ctx, db.baseDB.WithParam(param, value))
|
||||
}
|
||||
4
vendor/github.com/go-pg/pg/v10/doc.go
generated
vendored
4
vendor/github.com/go-pg/pg/v10/doc.go
generated
vendored
|
|
@ -1,4 +0,0 @@
|
|||
/*
|
||||
pg provides PostgreSQL client.
|
||||
*/
|
||||
package pg
|
||||
69
vendor/github.com/go-pg/pg/v10/error.go
generated
vendored
69
vendor/github.com/go-pg/pg/v10/error.go
generated
vendored
|
|
@ -1,69 +0,0 @@
|
|||
package pg
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/go-pg/pg/v10/internal"
|
||||
)
|
||||
|
||||
// ErrNoRows is returned by QueryOne and ExecOne when query returned zero rows
|
||||
// but at least one row is expected.
|
||||
var ErrNoRows = internal.ErrNoRows
|
||||
|
||||
// ErrMultiRows is returned by QueryOne and ExecOne when query returned
|
||||
// multiple rows but exactly one row is expected.
|
||||
var ErrMultiRows = internal.ErrMultiRows
|
||||
|
||||
// Error represents an error returned by PostgreSQL server
|
||||
// using PostgreSQL ErrorResponse protocol.
|
||||
//
|
||||
// https://www.postgresql.org/docs/10/static/protocol-message-formats.html
|
||||
type Error interface {
|
||||
error
|
||||
|
||||
// Field returns a string value associated with an error field.
|
||||
//
|
||||
// https://www.postgresql.org/docs/10/static/protocol-error-fields.html
|
||||
Field(field byte) string
|
||||
|
||||
// IntegrityViolation reports whether an error is a part of
|
||||
// Integrity Constraint Violation class of errors.
|
||||
//
|
||||
// https://www.postgresql.org/docs/10/static/errcodes-appendix.html
|
||||
IntegrityViolation() bool
|
||||
}
|
||||
|
||||
var _ Error = (*internal.PGError)(nil)
|
||||
|
||||
func isBadConn(err error, allowTimeout bool) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
if _, ok := err.(internal.Error); ok {
|
||||
return false
|
||||
}
|
||||
if pgErr, ok := err.(Error); ok {
|
||||
switch pgErr.Field('V') {
|
||||
case "FATAL", "PANIC":
|
||||
return true
|
||||
}
|
||||
switch pgErr.Field('C') {
|
||||
case "25P02", // current transaction is aborted
|
||||
"57014": // canceling statement due to user request
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
if allowTimeout {
|
||||
if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
|
||||
return !netErr.Temporary()
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
type timeoutError interface {
|
||||
Timeout() bool
|
||||
}
|
||||
24
vendor/github.com/go-pg/pg/v10/go.mod
generated
vendored
24
vendor/github.com/go-pg/pg/v10/go.mod
generated
vendored
|
|
@ -1,24 +0,0 @@
|
|||
module github.com/go-pg/pg/v10
|
||||
|
||||
go 1.11
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/go-pg/zerochecker v0.2.0
|
||||
github.com/golang/protobuf v1.4.3 // indirect
|
||||
github.com/google/go-cmp v0.5.5 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
||||
github.com/onsi/ginkgo v1.14.2
|
||||
github.com/onsi/gomega v1.10.3
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc
|
||||
github.com/vmihailenco/bufpool v0.1.11
|
||||
github.com/vmihailenco/msgpack/v5 v5.3.1
|
||||
github.com/vmihailenco/tagparser v0.1.2
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b // indirect
|
||||
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 // indirect
|
||||
google.golang.org/protobuf v1.25.0 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f
|
||||
mellium.im/sasl v0.2.1
|
||||
)
|
||||
154
vendor/github.com/go-pg/pg/v10/go.sum
generated
vendored
154
vendor/github.com/go-pg/pg/v10/go.sum
generated
vendored
|
|
@ -1,154 +0,0 @@
|
|||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/go-pg/zerochecker v0.2.0 h1:pp7f72c3DobMWOb2ErtZsnrPaSvHd2W4o9//8HtF4mU=
|
||||
github.com/go-pg/zerochecker v0.2.0/go.mod h1:NJZ4wKL0NmTtz0GKCoJ8kym6Xn/EQzXRl2OnAe7MmDo=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
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 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.14.2 h1:8mVmC9kjFFmA8H4pKMUhcblgifdkOIXPvbhN1T36q1M=
|
||||
github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.10.3 h1:gph6h/qe9GSUw1NhH1gp+qb+h8rXD8Cy60Z32Qw3ELA=
|
||||
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo=
|
||||
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc/go.mod h1:bciPuU6GHm1iF1pBvUfxfsH0Wmnc2VbpgvbI9ZWuIRs=
|
||||
github.com/vmihailenco/bufpool v0.1.11 h1:gOq2WmBrq0i2yW5QJ16ykccQ4wH9UyEsgLm6czKAd94=
|
||||
github.com/vmihailenco/bufpool v0.1.11/go.mod h1:AFf/MOy3l2CFTKbxwt0mp2MwnqjNEs5H/UxrkA5jxTQ=
|
||||
github.com/vmihailenco/msgpack/v5 v5.3.1 h1:0i85a4dsZh8mC//wmyyTEzidDLPQfQAxZIOLtafGbFY=
|
||||
github.com/vmihailenco/msgpack/v5 v5.3.1/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc=
|
||||
github.com/vmihailenco/tagparser v0.1.2 h1:gnjoVuB/kljJ5wICEEOpx98oXMWPLj22G67Vbd1qPqc=
|
||||
github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
|
||||
golang.org/x/crypto v0.0.0-20180910181607-0e37d006457b/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-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b h1:7mWr3k41Qtv8XlltBkDkl8LoP3mpSgBW8BUoxtEdbXg=
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/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-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw=
|
||||
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
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/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
mellium.im/sasl v0.2.1 h1:nspKSRg7/SyO0cRGY71OkfHab8tf9kCts6a6oTDut0w=
|
||||
mellium.im/sasl v0.2.1/go.mod h1:ROaEDLQNuf9vjKqE1SrAfnsobm2YKXT1gnN1uDp1PjQ=
|
||||
139
vendor/github.com/go-pg/pg/v10/hook.go
generated
vendored
139
vendor/github.com/go-pg/pg/v10/hook.go
generated
vendored
|
|
@ -1,139 +0,0 @@
|
|||
package pg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/go-pg/pg/v10/orm"
|
||||
)
|
||||
|
||||
type (
|
||||
BeforeScanHook = orm.BeforeScanHook
|
||||
AfterScanHook = orm.AfterScanHook
|
||||
AfterSelectHook = orm.AfterSelectHook
|
||||
BeforeInsertHook = orm.BeforeInsertHook
|
||||
AfterInsertHook = orm.AfterInsertHook
|
||||
BeforeUpdateHook = orm.BeforeUpdateHook
|
||||
AfterUpdateHook = orm.AfterUpdateHook
|
||||
BeforeDeleteHook = orm.BeforeDeleteHook
|
||||
AfterDeleteHook = orm.AfterDeleteHook
|
||||
)
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
type dummyFormatter struct{}
|
||||
|
||||
func (dummyFormatter) FormatQuery(b []byte, query string, params ...interface{}) []byte {
|
||||
return append(b, query...)
|
||||
}
|
||||
|
||||
// QueryEvent ...
|
||||
type QueryEvent struct {
|
||||
StartTime time.Time
|
||||
DB orm.DB
|
||||
Model interface{}
|
||||
Query interface{}
|
||||
Params []interface{}
|
||||
fmtedQuery []byte
|
||||
Result Result
|
||||
Err error
|
||||
|
||||
Stash map[interface{}]interface{}
|
||||
}
|
||||
|
||||
// QueryHook ...
|
||||
type QueryHook interface {
|
||||
BeforeQuery(context.Context, *QueryEvent) (context.Context, error)
|
||||
AfterQuery(context.Context, *QueryEvent) error
|
||||
}
|
||||
|
||||
// UnformattedQuery returns the unformatted query of a query event.
|
||||
// The query is only valid until the query Result is returned to the user.
|
||||
func (e *QueryEvent) UnformattedQuery() ([]byte, error) {
|
||||
return queryString(e.Query)
|
||||
}
|
||||
|
||||
func queryString(query interface{}) ([]byte, error) {
|
||||
switch query := query.(type) {
|
||||
case orm.TemplateAppender:
|
||||
return query.AppendTemplate(nil)
|
||||
case string:
|
||||
return dummyFormatter{}.FormatQuery(nil, query), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("pg: can't append %T", query)
|
||||
}
|
||||
}
|
||||
|
||||
// FormattedQuery returns the formatted query of a query event.
|
||||
// The query is only valid until the query Result is returned to the user.
|
||||
func (e *QueryEvent) FormattedQuery() ([]byte, error) {
|
||||
return e.fmtedQuery, nil
|
||||
}
|
||||
|
||||
// AddQueryHook adds a hook into query processing.
|
||||
func (db *baseDB) AddQueryHook(hook QueryHook) {
|
||||
db.queryHooks = append(db.queryHooks, hook)
|
||||
}
|
||||
|
||||
func (db *baseDB) beforeQuery(
|
||||
ctx context.Context,
|
||||
ormDB orm.DB,
|
||||
model, query interface{},
|
||||
params []interface{},
|
||||
fmtedQuery []byte,
|
||||
) (context.Context, *QueryEvent, error) {
|
||||
if len(db.queryHooks) == 0 {
|
||||
return ctx, nil, nil
|
||||
}
|
||||
|
||||
event := &QueryEvent{
|
||||
StartTime: time.Now(),
|
||||
DB: ormDB,
|
||||
Model: model,
|
||||
Query: query,
|
||||
Params: params,
|
||||
fmtedQuery: fmtedQuery,
|
||||
}
|
||||
|
||||
for i, hook := range db.queryHooks {
|
||||
var err error
|
||||
ctx, err = hook.BeforeQuery(ctx, event)
|
||||
if err != nil {
|
||||
if err := db.afterQueryFromIndex(ctx, event, i); err != nil {
|
||||
return ctx, nil, err
|
||||
}
|
||||
return ctx, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return ctx, event, nil
|
||||
}
|
||||
|
||||
func (db *baseDB) afterQuery(
|
||||
ctx context.Context,
|
||||
event *QueryEvent,
|
||||
res Result,
|
||||
err error,
|
||||
) error {
|
||||
if event == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
event.Err = err
|
||||
event.Result = res
|
||||
return db.afterQueryFromIndex(ctx, event, len(db.queryHooks)-1)
|
||||
}
|
||||
|
||||
func (db *baseDB) afterQueryFromIndex(ctx context.Context, event *QueryEvent, hookIndex int) error {
|
||||
for ; hookIndex >= 0; hookIndex-- {
|
||||
if err := db.queryHooks[hookIndex].AfterQuery(ctx, event); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func copyQueryHooks(s []QueryHook) []QueryHook {
|
||||
return s[:len(s):len(s)]
|
||||
}
|
||||
26
vendor/github.com/go-pg/pg/v10/internal/context.go
generated
vendored
26
vendor/github.com/go-pg/pg/v10/internal/context.go
generated
vendored
|
|
@ -1,26 +0,0 @@
|
|||
package internal
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
)
|
||||
|
||||
type UndoneContext struct {
|
||||
context.Context
|
||||
}
|
||||
|
||||
func UndoContext(ctx context.Context) UndoneContext {
|
||||
return UndoneContext{Context: ctx}
|
||||
}
|
||||
|
||||
func (UndoneContext) Deadline() (deadline time.Time, ok bool) {
|
||||
return time.Time{}, false
|
||||
}
|
||||
|
||||
func (UndoneContext) Done() <-chan struct{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (UndoneContext) Err() error {
|
||||
return nil
|
||||
}
|
||||
61
vendor/github.com/go-pg/pg/v10/internal/error.go
generated
vendored
61
vendor/github.com/go-pg/pg/v10/internal/error.go
generated
vendored
|
|
@ -1,61 +0,0 @@
|
|||
package internal
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrNoRows = Errorf("pg: no rows in result set")
|
||||
ErrMultiRows = Errorf("pg: multiple rows in result set")
|
||||
)
|
||||
|
||||
type Error struct {
|
||||
s string
|
||||
}
|
||||
|
||||
func Errorf(s string, args ...interface{}) Error {
|
||||
return Error{s: fmt.Sprintf(s, args...)}
|
||||
}
|
||||
|
||||
func (err Error) Error() string {
|
||||
return err.s
|
||||
}
|
||||
|
||||
type PGError struct {
|
||||
m map[byte]string
|
||||
}
|
||||
|
||||
func NewPGError(m map[byte]string) PGError {
|
||||
return PGError{
|
||||
m: m,
|
||||
}
|
||||
}
|
||||
|
||||
func (err PGError) Field(k byte) string {
|
||||
return err.m[k]
|
||||
}
|
||||
|
||||
func (err PGError) IntegrityViolation() bool {
|
||||
switch err.Field('C') {
|
||||
case "23000", "23001", "23502", "23503", "23505", "23514", "23P01":
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (err PGError) Error() string {
|
||||
return fmt.Sprintf("%s #%s %s",
|
||||
err.Field('S'), err.Field('C'), err.Field('M'))
|
||||
}
|
||||
|
||||
func AssertOneRow(l int) error {
|
||||
switch {
|
||||
case l == 0:
|
||||
return ErrNoRows
|
||||
case l > 1:
|
||||
return ErrMultiRows
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
27
vendor/github.com/go-pg/pg/v10/internal/internal.go
generated
vendored
27
vendor/github.com/go-pg/pg/v10/internal/internal.go
generated
vendored
|
|
@ -1,27 +0,0 @@
|
|||
/*
|
||||
internal is a private internal package.
|
||||
*/
|
||||
package internal
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
func RetryBackoff(retry int, minBackoff, maxBackoff time.Duration) time.Duration {
|
||||
if retry < 0 {
|
||||
panic("not reached")
|
||||
}
|
||||
if minBackoff == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
d := minBackoff << uint(retry)
|
||||
d = minBackoff + time.Duration(rand.Int63n(int64(d)))
|
||||
|
||||
if d > maxBackoff || d < minBackoff {
|
||||
d = maxBackoff
|
||||
}
|
||||
|
||||
return d
|
||||
}
|
||||
28
vendor/github.com/go-pg/pg/v10/internal/log.go
generated
vendored
28
vendor/github.com/go-pg/pg/v10/internal/log.go
generated
vendored
|
|
@ -1,28 +0,0 @@
|
|||
package internal
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
var Warn = log.New(os.Stderr, "WARN: pg: ", log.LstdFlags)
|
||||
|
||||
var Deprecated = log.New(os.Stderr, "DEPRECATED: pg: ", log.LstdFlags)
|
||||
|
||||
type Logging interface {
|
||||
Printf(ctx context.Context, format string, v ...interface{})
|
||||
}
|
||||
|
||||
type logger struct {
|
||||
log *log.Logger
|
||||
}
|
||||
|
||||
func (l *logger) Printf(ctx context.Context, format string, v ...interface{}) {
|
||||
_ = l.log.Output(2, fmt.Sprintf(format, v...))
|
||||
}
|
||||
|
||||
var Logger Logging = &logger{
|
||||
log: log.New(os.Stderr, "pg: ", log.LstdFlags|log.Lshortfile),
|
||||
}
|
||||
141
vendor/github.com/go-pg/pg/v10/internal/parser/parser.go
generated
vendored
141
vendor/github.com/go-pg/pg/v10/internal/parser/parser.go
generated
vendored
|
|
@ -1,141 +0,0 @@
|
|||
package parser
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strconv"
|
||||
|
||||
"github.com/go-pg/pg/v10/internal"
|
||||
)
|
||||
|
||||
type Parser struct {
|
||||
b []byte
|
||||
i int
|
||||
}
|
||||
|
||||
func New(b []byte) *Parser {
|
||||
return &Parser{
|
||||
b: b,
|
||||
}
|
||||
}
|
||||
|
||||
func NewString(s string) *Parser {
|
||||
return New(internal.StringToBytes(s))
|
||||
}
|
||||
|
||||
func (p *Parser) Valid() bool {
|
||||
return p.i < len(p.b)
|
||||
}
|
||||
|
||||
func (p *Parser) Bytes() []byte {
|
||||
return p.b[p.i:]
|
||||
}
|
||||
|
||||
func (p *Parser) Read() byte {
|
||||
if p.Valid() {
|
||||
c := p.b[p.i]
|
||||
p.Advance()
|
||||
return c
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (p *Parser) Peek() byte {
|
||||
if p.Valid() {
|
||||
return p.b[p.i]
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (p *Parser) Advance() {
|
||||
p.i++
|
||||
}
|
||||
|
||||
func (p *Parser) Skip(skip byte) bool {
|
||||
if p.Peek() == skip {
|
||||
p.Advance()
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *Parser) SkipBytes(skip []byte) bool {
|
||||
if len(skip) > len(p.b[p.i:]) {
|
||||
return false
|
||||
}
|
||||
if !bytes.Equal(p.b[p.i:p.i+len(skip)], skip) {
|
||||
return false
|
||||
}
|
||||
p.i += len(skip)
|
||||
return true
|
||||
}
|
||||
|
||||
func (p *Parser) ReadSep(sep byte) ([]byte, bool) {
|
||||
ind := bytes.IndexByte(p.b[p.i:], sep)
|
||||
if ind == -1 {
|
||||
b := p.b[p.i:]
|
||||
p.i = len(p.b)
|
||||
return b, false
|
||||
}
|
||||
|
||||
b := p.b[p.i : p.i+ind]
|
||||
p.i += ind + 1
|
||||
return b, true
|
||||
}
|
||||
|
||||
func (p *Parser) ReadIdentifier() (string, bool) {
|
||||
if p.i < len(p.b) && p.b[p.i] == '(' {
|
||||
s := p.i + 1
|
||||
if ind := bytes.IndexByte(p.b[s:], ')'); ind != -1 {
|
||||
b := p.b[s : s+ind]
|
||||
p.i = s + ind + 1
|
||||
return internal.BytesToString(b), false
|
||||
}
|
||||
}
|
||||
|
||||
ind := len(p.b) - p.i
|
||||
var alpha bool
|
||||
for i, c := range p.b[p.i:] {
|
||||
if isNum(c) {
|
||||
continue
|
||||
}
|
||||
if isAlpha(c) || (i > 0 && alpha && c == '_') {
|
||||
alpha = true
|
||||
continue
|
||||
}
|
||||
ind = i
|
||||
break
|
||||
}
|
||||
if ind == 0 {
|
||||
return "", false
|
||||
}
|
||||
b := p.b[p.i : p.i+ind]
|
||||
p.i += ind
|
||||
return internal.BytesToString(b), !alpha
|
||||
}
|
||||
|
||||
func (p *Parser) ReadNumber() int {
|
||||
ind := len(p.b) - p.i
|
||||
for i, c := range p.b[p.i:] {
|
||||
if !isNum(c) {
|
||||
ind = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if ind == 0 {
|
||||
return 0
|
||||
}
|
||||
n, err := strconv.Atoi(string(p.b[p.i : p.i+ind]))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
p.i += ind
|
||||
return n
|
||||
}
|
||||
|
||||
func isNum(c byte) bool {
|
||||
return c >= '0' && c <= '9'
|
||||
}
|
||||
|
||||
func isAlpha(c byte) bool {
|
||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue