mirror of
https://github.com/tgdrive/teldrive.git
synced 2025-02-21 21:44:07 +08:00
api changes
This commit is contained in:
parent
8ee3e8b846
commit
b040eb9e1e
22 changed files with 284 additions and 428 deletions
35
.github/workflows/dev.yml
vendored
35
.github/workflows/dev.yml
vendored
|
@ -1,35 +0,0 @@
|
|||
# .github/workflows/release.yaml
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
releases-matrix:
|
||||
name: Release Go Binary
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
goos: [linux]
|
||||
goarch: [amd64]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
|
||||
- uses: divyam234/go-release-action@master
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
goos: ${{ matrix.goos }}
|
||||
goarch: ${{ matrix.goarch }}
|
||||
binary_name: "teldrive"
|
||||
extra_files: LICENSE README.md
|
||||
goversion: "https://dl.google.com/go/go1.21.1.linux-amd64.tar.gz"
|
||||
pre_command: make pre-ui && make ui && export CGO_ENABLED=0
|
||||
release_tag: canary
|
||||
overwrite: true
|
||||
ldflags: -s -w -extldflags=-static
|
|
@ -9,6 +9,9 @@ before:
|
|||
builds:
|
||||
- env:
|
||||
- CGO_ENABLED=0
|
||||
main:
|
||||
- cmd/teldrive/main.go
|
||||
|
||||
flags:
|
||||
- -trimpath
|
||||
ldflags:
|
||||
|
|
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
|
@ -9,7 +9,7 @@
|
|||
"type": "go",
|
||||
"request": "launch",
|
||||
"mode": "auto",
|
||||
"program": "main.go"
|
||||
"program": "cmd/teldrive/main.go"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -13,9 +13,6 @@ func InitRouter() *gin.Engine {
|
|||
|
||||
r.Use(gin.Logger())
|
||||
|
||||
// if gin.Mode() == gin.ReleaseMode {
|
||||
// r.Use(middleware.Security())
|
||||
// }
|
||||
r.Use(middleware.Cors())
|
||||
|
||||
c := controller.NewController()
|
||||
|
@ -54,7 +51,7 @@ func InitRouter() *gin.Engine {
|
|||
}
|
||||
users := api.Group("/users")
|
||||
{
|
||||
uploads.Use(middleware.Authmiddleware)
|
||||
users.Use(middleware.Authmiddleware)
|
||||
users.GET("/profile", c.GetProfilePhoto)
|
||||
users.GET("/stats", c.Stats)
|
||||
users.GET("/bots", c.GetBots)
|
||||
|
|
|
@ -4,11 +4,14 @@ import (
|
|||
"fmt"
|
||||
"mime"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/divyam234/teldrive/api"
|
||||
"github.com/divyam234/teldrive/internal/cron"
|
||||
"github.com/divyam234/teldrive/internal/logger"
|
||||
"github.com/divyam234/teldrive/internal/utils"
|
||||
"github.com/divyam234/teldrive/pkg/database"
|
||||
"github.com/go-co-op/gocron"
|
||||
|
||||
cnf "github.com/divyam234/teldrive/config"
|
||||
"github.com/divyam234/teldrive/internal/cache"
|
||||
|
@ -27,13 +30,13 @@ func main() {
|
|||
|
||||
cache.InitCache()
|
||||
|
||||
// scheduler := gocron.NewScheduler(time.UTC)
|
||||
scheduler := gocron.NewScheduler(time.UTC)
|
||||
|
||||
// scheduler.Every(1).Hour().Do(cron.FilesDeleteJob)
|
||||
scheduler.Every(1).Hour().Do(cron.FilesDeleteJob)
|
||||
|
||||
// scheduler.Every(12).Hour().Do(cron.UploadCleanJob)
|
||||
scheduler.Every(12).Hour().Do(cron.UploadCleanJob)
|
||||
|
||||
// scheduler.StartAsync()
|
||||
scheduler.StartAsync()
|
||||
|
||||
mime.AddExtensionType(".js", "application/javascript")
|
||||
|
||||
|
|
3
go.mod
3
go.mod
|
@ -26,7 +26,10 @@ require (
|
|||
require (
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/chenzhuoyu/iasm v0.9.1 // indirect
|
||||
github.com/go-co-op/gocron v1.36.0 // indirect
|
||||
github.com/google/uuid v1.4.0 // indirect
|
||||
github.com/jackc/puddle/v2 v2.2.1 // indirect
|
||||
github.com/robfig/cron/v3 v3.0.1 // indirect
|
||||
github.com/sethvargo/go-retry v0.2.4 // indirect
|
||||
golang.org/x/tools v0.16.0 // indirect
|
||||
)
|
||||
|
|
6
go.sum
6
go.sum
|
@ -64,6 +64,8 @@ github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmC
|
|||
github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk=
|
||||
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
|
||||
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
|
||||
github.com/go-co-op/gocron v1.36.0 h1:sEmAwg57l4JWQgzaVWYfKZ+w13uHOqeOtwjo72Ll5Wc=
|
||||
github.com/go-co-op/gocron v1.36.0/go.mod h1:3L/n6BkO7ABj+TrfSVXLRzsP26zmikL4ISkLQ0O8iNY=
|
||||
github.com/go-faster/city v1.0.1 h1:4WAxSZ3V2Ws4QRDrscLEDcibJY8uf41H6AhXDrNDcGw=
|
||||
github.com/go-faster/city v1.0.1/go.mod h1:jKcUJId49qdW3L1qKHH/3wPeUstCVpVSXTM6vO3VcTw=
|
||||
github.com/go-faster/errors v0.7.0 h1:UnD/xusnfUgtEYkgRZohqL2AfmPTwv13NAJwwFFaNYc=
|
||||
|
@ -209,8 +211,11 @@ github.com/quantumsheep/range-parser v1.1.0 h1:k4f1F58f8FF54FBYc9dYBRM+8JkAxFo11
|
|||
github.com/quantumsheep/range-parser v1.1.0/go.mod h1:acv4Vt2PvpGvRsvGju7Gk2ahKluZJsIUNR69W53J22I=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||
github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
|
||||
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
||||
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
|
||||
github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
|
||||
|
@ -262,6 +267,7 @@ go.opentelemetry.io/otel v1.20.0 h1:vsb/ggIY+hUjD/zCAQHpzTmndPqv/ml2ArbsbfBYTAc=
|
|||
go.opentelemetry.io/otel v1.20.0/go.mod h1:oUIGj3D77RwJdM6PPZImDpSZGDvkD9fhesHny69JFrs=
|
||||
go.opentelemetry.io/otel/trace v1.20.0 h1:+yxVAPZPbQhbC3OfAkeIVTky6iTFpcr4SiY9om7mXSQ=
|
||||
go.opentelemetry.io/otel/trace v1.20.0/go.mod h1:HJSK7F/hA5RlzpZ0zKDCHCDHm556LCDtKaAo6JmBFUU=
|
||||
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
|
||||
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
|
||||
|
|
|
@ -13,7 +13,7 @@ func InitLogger() {
|
|||
config := zap.NewProductionEncoderConfig()
|
||||
config.EncodeTime = zapcore.ISO8601TimeEncoder
|
||||
consoleEncoder := zapcore.NewConsoleEncoder(config)
|
||||
defaultLogLevel := zapcore.DebugLevel
|
||||
defaultLogLevel := zapcore.InfoLevel
|
||||
core := zapcore.NewCore(consoleEncoder, zapcore.AddSync(os.Stdout), defaultLogLevel)
|
||||
Logger = zap.New(core, zap.AddCaller(), zap.AddStacktrace(zapcore.ErrorLevel))
|
||||
}
|
||||
|
|
|
@ -61,10 +61,9 @@ func InitDB() {
|
|||
}
|
||||
sqlDB.SetMaxIdleConns(25)
|
||||
sqlDB.SetMaxOpenConns(25)
|
||||
sqlDB.SetConnMaxIdleTime(10 * time.Minute)
|
||||
|
||||
sqlDB.SetConnMaxLifetime(time.Hour)
|
||||
go func() {
|
||||
DB.Exec(`create collation if not exists numeric (provider = icu, locale = 'en@colnumeric=yes');`)
|
||||
if config.RunMigrations {
|
||||
migrate()
|
||||
}
|
||||
|
|
|
@ -1,66 +1,55 @@
|
|||
-- +goose Up
|
||||
create extension if not exists pgcrypto;
|
||||
|
||||
create extension if not exists btree_gin;
|
||||
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
||||
|
||||
create schema if not exists teldrive;
|
||||
CREATE EXTENSION IF NOT EXISTS btree_gin;
|
||||
|
||||
create collation if not exists numeric (provider = icu, locale = 'en@colnumeric=yes');
|
||||
CREATE SCHEMA IF NOT EXISTS teldrive;
|
||||
|
||||
CREATE COLLATION IF NOT EXISTS numeric (PROVIDER = ICU, LOCALE = 'en@colnumeric=yes');
|
||||
|
||||
-- +goose StatementBegin
|
||||
create or replace
|
||||
function teldrive.generate_uid(size int) returns text language plpgsql as $$
|
||||
declare characters text := 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
|
||||
bytes bytea := gen_random_bytes(size);
|
||||
CREATE OR REPLACE
|
||||
FUNCTION teldrive.generate_uid(size INT) RETURNS TEXT LANGUAGE PLPGSQL AS $$
|
||||
DECLARE
|
||||
characters TEXT := 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
bytes BYTEA := gen_random_bytes(size);
|
||||
l INT := LENGTH(characters);
|
||||
i INT := 0;
|
||||
output TEXT := '';
|
||||
BEGIN
|
||||
WHILE i < size LOOP
|
||||
output := output || SUBSTR(characters, GET_BYTE(bytes, i) % l + 1, 1);
|
||||
i := i + 1;
|
||||
END LOOP;
|
||||
RETURN output;
|
||||
END;
|
||||
$$;
|
||||
|
||||
l int := length(characters);
|
||||
|
||||
i int := 0;
|
||||
|
||||
output text := '';
|
||||
|
||||
begin while i < size loop output := output || substr(characters,
|
||||
get_byte(bytes,
|
||||
i) % l + 1,
|
||||
1);
|
||||
|
||||
i := i + 1;
|
||||
end loop;
|
||||
|
||||
return output;
|
||||
end;
|
||||
CREATE OR REPLACE
|
||||
FUNCTION teldrive.get_tsvector(t TEXT) RETURNS TSVECTOR LANGUAGE PLPGSQL IMMUTABLE AS $$
|
||||
DECLARE
|
||||
res TSVECTOR := to_tsvector(regexp_replace(t, '[^A-Za-z0-9 ]', ' ', 'g'));
|
||||
BEGIN
|
||||
RETURN res;
|
||||
END;
|
||||
$$;
|
||||
|
||||
CREATE OR REPLACE
|
||||
FUNCTION teldrive.get_tsquery(t TEXT) RETURNS TSQUERY LANGUAGE PLPGSQL IMMUTABLE AS $$
|
||||
DECLARE
|
||||
res TSQUERY := CONCAT(plainto_tsquery(regexp_replace(t, '[^A-Za-z0-9 ]', ' ', 'g')), ':*')::TSQUERY;
|
||||
BEGIN
|
||||
RETURN res;
|
||||
END;
|
||||
$$;
|
||||
-- +goose StatementEnd
|
||||
|
||||
|
||||
-- +goose Down
|
||||
-- +goose StatementBegin
|
||||
create or replace
|
||||
function teldrive.get_tsvector(t text) returns tsvector language plpgsql immutable as $$
|
||||
declare res tsvector := to_tsvector(regexp_replace(t,
|
||||
'[^A-Za-z0-9 ]',
|
||||
' ',
|
||||
'g'));
|
||||
|
||||
begin return res;
|
||||
end;
|
||||
|
||||
$$;
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose StatementBegin
|
||||
create or replace
|
||||
function teldrive.get_tsquery(t text) returns tsquery language plpgsql immutable as $$
|
||||
declare res tsquery = concat(
|
||||
plainto_tsquery(regexp_replace(t,
|
||||
'[^A-Za-z0-9 ]',
|
||||
' ',
|
||||
'g')),
|
||||
':*'
|
||||
)::tsquery;
|
||||
|
||||
begin return res;
|
||||
end;
|
||||
|
||||
$$;
|
||||
DROP FUNCTION IF EXISTS teldrive.generate_uid;
|
||||
DROP FUNCTION IF EXISTS teldrive.get_tsvector;
|
||||
DROP FUNCTION IF EXISTS teldrive.get_tsquery;
|
||||
-- +goose StatementEnd
|
||||
|
|
|
@ -1,88 +0,0 @@
|
|||
-- +goose Up
|
||||
create table teldrive.files (
|
||||
id text primary key not null default teldrive.generate_uid(16),
|
||||
name text not null,
|
||||
type text not null,
|
||||
mime_type text not null,
|
||||
path text null,
|
||||
size bigint null,
|
||||
starred bool not null,
|
||||
depth integer null,
|
||||
user_id bigint not null,
|
||||
parent_id text null,
|
||||
status text default 'active'::text,
|
||||
channel_id bigint null,
|
||||
parts jsonb null,
|
||||
created_at timestamp not null default timezone('utc'::text,
|
||||
now()),
|
||||
updated_at timestamp not null default timezone('utc'::text,
|
||||
now()),
|
||||
constraint unique_file unique (name,
|
||||
parent_id,user_id)
|
||||
);
|
||||
|
||||
create table teldrive.uploads (
|
||||
id text not null primary key default teldrive.generate_uid(16),
|
||||
upload_id text not null,
|
||||
name text not null,
|
||||
part_no int4 not null,
|
||||
part_id int4 not null,
|
||||
total_parts int4 not null,
|
||||
channel_id int8 not null,
|
||||
size int8 not null,
|
||||
created_at timestamp null default timezone('utc'::text,
|
||||
now())
|
||||
);
|
||||
|
||||
create table teldrive.users (
|
||||
user_id bigint not null primary key,
|
||||
name text null,
|
||||
user_name text null,
|
||||
is_premium bool not null,
|
||||
tg_session text not null,
|
||||
settings jsonb null,
|
||||
created_at timestamptz not null default timezone('utc'::text,
|
||||
now()),
|
||||
updated_at timestamptz not null default timezone('utc'::text,
|
||||
now())
|
||||
);
|
||||
|
||||
create collation if not exists numeric (provider = icu, locale = 'en@colnumeric=yes');
|
||||
create index name_search_idx on
|
||||
teldrive.files
|
||||
using gin (teldrive.get_tsvector(name),
|
||||
updated_at);
|
||||
|
||||
create index name_numeric_idx on
|
||||
teldrive.files(name collate numeric nulls first);
|
||||
|
||||
create index parent_name_numeric_idx on
|
||||
teldrive.files (parent_id,
|
||||
name collate numeric desc);
|
||||
|
||||
create index path_idx on
|
||||
teldrive.files (path);
|
||||
|
||||
create index parent_idx on
|
||||
teldrive.files (parent_id);
|
||||
|
||||
create index starred_updated_at_idx on
|
||||
teldrive.files (starred,
|
||||
updated_at desc);
|
||||
|
||||
create index status_idx on teldrive.files (status);
|
||||
|
||||
create index user_id_idx on teldrive.files (user_id);
|
||||
|
||||
-- +goose Down
|
||||
drop table if exists teldrive.files;
|
||||
drop table if exists teldrive.uploads;
|
||||
drop table if exists teldrive.users;
|
||||
drop index if exists teldrive.name_search_idx;
|
||||
drop index if exists teldrive.name_numeric_idx;
|
||||
drop index if exists teldrive.parent_name_numeric_idx;
|
||||
drop index if exists teldrive.path_idx;
|
||||
drop index if exists teldrive.parent_idx;
|
||||
drop index if exists teldrive.starred_updated_at_idx;
|
||||
drop index if exists teldrive.status_idx;
|
||||
drop index if exists teldrive.user_id_idx;
|
|
@ -1,116 +0,0 @@
|
|||
-- +goose Up
|
||||
|
||||
-- +goose StatementBegin
|
||||
create procedure teldrive.update_size() language plpgsql as $$
|
||||
declare rec record;
|
||||
|
||||
total_size bigint;
|
||||
|
||||
begin
|
||||
|
||||
for rec in
|
||||
select
|
||||
id
|
||||
from
|
||||
files
|
||||
where
|
||||
type = 'folder'
|
||||
order by
|
||||
depth desc loop total_size := (
|
||||
select
|
||||
sum(size) as total_size
|
||||
from
|
||||
teldrive.files
|
||||
where
|
||||
parent_id = rec.id
|
||||
);
|
||||
|
||||
update
|
||||
teldrive.files
|
||||
set
|
||||
size = total_size
|
||||
where
|
||||
id = rec.id;
|
||||
end loop;
|
||||
end;
|
||||
|
||||
$$;
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose StatementBegin
|
||||
create procedure teldrive.delete_files(in file_ids text[],
|
||||
in op text default 'bulk')
|
||||
language plpgsql
|
||||
as $$
|
||||
declare
|
||||
rec record;
|
||||
|
||||
begin
|
||||
if op = 'bulk' then
|
||||
for rec in
|
||||
select
|
||||
id,
|
||||
type
|
||||
from
|
||||
teldrive.files
|
||||
where
|
||||
id = any (file_ids)
|
||||
loop
|
||||
if rec.type = 'folder' then
|
||||
call teldrive.delete_files(array [rec.id],
|
||||
'single');
|
||||
|
||||
delete
|
||||
from
|
||||
teldrive.files
|
||||
where
|
||||
id = rec.id;
|
||||
else
|
||||
update
|
||||
teldrive.files
|
||||
set
|
||||
status = 'pending_deletion'
|
||||
where
|
||||
id = rec.id;
|
||||
end if;
|
||||
end loop;
|
||||
else
|
||||
|
||||
for rec in
|
||||
select
|
||||
id,
|
||||
type
|
||||
from
|
||||
teldrive.files
|
||||
where
|
||||
parent_id = file_ids[1]
|
||||
loop
|
||||
if rec.type = 'folder' then
|
||||
call teldrive.delete_files(array [rec.id],
|
||||
'single');
|
||||
|
||||
delete
|
||||
from
|
||||
teldrive.files
|
||||
where
|
||||
id = rec.id;
|
||||
else
|
||||
update
|
||||
teldrive.files
|
||||
set
|
||||
status = 'pending_deletion'
|
||||
where
|
||||
id = rec.id;
|
||||
end if;
|
||||
end loop;
|
||||
end if;
|
||||
end;
|
||||
|
||||
$$
|
||||
;
|
||||
-- +goose StatementEnd
|
||||
|
||||
|
||||
-- +goose Down
|
||||
drop procedure if exists teldrive.update_size;
|
||||
drop procedure if exists teldrive.delete_files;
|
|
@ -1,7 +0,0 @@
|
|||
-- +goose Up
|
||||
|
||||
ALTER TABLE teldrive.files DROP CONSTRAINT IF EXISTS unique_file;
|
||||
|
||||
ALTER TABLE teldrive.users DROP COLUMN settings;
|
||||
|
||||
CREATE UNIQUE INDEX unique_file ON teldrive.files (name, parent_id, user_id) WHERE (status= 'active');
|
|
@ -1,27 +0,0 @@
|
|||
-- +goose Up
|
||||
-- +goose StatementBegin
|
||||
|
||||
CREATE TABLE teldrive.bots (
|
||||
user_id bigint NOT NULL,
|
||||
token text NOT NULL,
|
||||
bot_user_name text NOT NULL,
|
||||
bot_id bigint NOT NULL,
|
||||
FOREIGN KEY (user_id) REFERENCES teldrive.users(user_id),
|
||||
CONSTRAINT btoken_user_un UNIQUE (user_id,token)
|
||||
);
|
||||
|
||||
CREATE TABLE teldrive.channels (
|
||||
channel_id bigint NOT NULL PRIMARY KEY,
|
||||
channel_name text NOT NULL,
|
||||
user_id bigint NOT NULL,
|
||||
selected boolean DEFAULT false,
|
||||
FOREIGN KEY (user_id) REFERENCES teldrive.users(user_id)
|
||||
);
|
||||
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose Down
|
||||
-- +goose StatementBegin
|
||||
DROP TABLE IF EXISTS teldrive.bots;
|
||||
DROP TABLE IF EXISTS teldrive.channels;
|
||||
-- +goose StatementEnd
|
|
@ -1,22 +0,0 @@
|
|||
-- +goose Up
|
||||
-- +goose StatementBegin
|
||||
CREATE OR REPLACE FUNCTION teldrive.account_stats(
|
||||
IN u_id BIGINT
|
||||
) RETURNS TABLE (total_size BIGINT, total_files BIGINT, ch_id BIGINT,ch_name TEXT ) AS $$
|
||||
DECLARE
|
||||
total_size BIGINT;
|
||||
total_files BIGINT;
|
||||
ch_id BIGINT;
|
||||
ch_name TEXT;
|
||||
BEGIN
|
||||
SELECT COUNT(*), SUM(size) into total_files,total_size FROM teldrive.files WHERE user_id=u_id AND type= 'file' and status='active';
|
||||
SELECT channel_id ,channel_name into ch_id,ch_name FROM teldrive.channels WHERE selected=TRUE AND user_id=u_id;
|
||||
RETURN QUERY SELECT total_size,total_files,ch_id,ch_name;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose Down
|
||||
-- +goose StatementBegin
|
||||
DROP FUNCTION IF EXISTS teldrive.account_stats;
|
||||
-- +goose StatementEnd
|
|
@ -1,7 +0,0 @@
|
|||
-- +goose Up
|
||||
|
||||
ALTER TABLE teldrive.bots ADD COLUMN channel_id BIGINT;
|
||||
|
||||
ALTER TABLE teldrive.bots DROP CONSTRAINT IF EXISTS btoken_user_un;
|
||||
|
||||
ALTER TABLE teldrive.bots ADD CONSTRAINT btoken_user_channel_un UNIQUE (user_id, token,channel_id);
|
|
@ -1,49 +0,0 @@
|
|||
-- +goose Up
|
||||
-- +goose StatementBegin
|
||||
|
||||
CREATE OR REPLACE FUNCTION teldrive.create_directories(
|
||||
IN tg_id BIGINT,
|
||||
IN long_path TEXT
|
||||
) RETURNS SETOF teldrive.files AS $$
|
||||
DECLARE
|
||||
path_parts TEXT[];
|
||||
current_directory_id TEXT;
|
||||
new_directory_id TEXT;
|
||||
directory_name TEXT;
|
||||
path_so_far TEXT;
|
||||
depth_dir integer;
|
||||
begin
|
||||
|
||||
path_parts := string_to_array(regexp_replace(long_path, '^/+', ''), '/');
|
||||
|
||||
path_so_far := '';
|
||||
|
||||
depth_dir := 0;
|
||||
|
||||
SELECT id into current_directory_id FROM teldrive.files WHERE parent_id='root' AND user_id=tg_id;
|
||||
|
||||
|
||||
FOR directory_name IN SELECT unnest(path_parts) LOOP
|
||||
path_so_far := CONCAT(path_so_far,'/', directory_name);
|
||||
depth_dir := depth_dir +1;
|
||||
SELECT id INTO new_directory_id
|
||||
FROM teldrive.files
|
||||
WHERE parent_id = current_directory_id
|
||||
AND "name" = directory_name AND "user_id"=tg_id;
|
||||
|
||||
IF new_directory_id IS NULL THEN
|
||||
INSERT INTO teldrive.files ("name", "type", mime_type, parent_id, "user_id",starred,"depth","path")
|
||||
VALUES (directory_name, 'folder', 'drive/folder', current_directory_id, tg_id,false,depth_dir,path_so_far)
|
||||
RETURNING id INTO new_directory_id;
|
||||
END IF;
|
||||
|
||||
current_directory_id := new_directory_id;
|
||||
END LOOP;
|
||||
|
||||
RETURN QUERY SELECT * FROM teldrive.files WHERE id = current_directory_id;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose Down
|
||||
DROP FUNCTION IF EXISTS teldrive.create_directories;
|
|
@ -1,3 +0,0 @@
|
|||
-- +goose Up
|
||||
|
||||
ALTER TABLE teldrive.uploads ADD COLUMN user_id BIGINT;
|
|
@ -1,20 +1,104 @@
|
|||
-- +goose Up
|
||||
-- +goose StatementBegin
|
||||
|
||||
ALTER TABLE teldrive.users DROP COLUMN IF EXISTS tg_session;
|
||||
CREATE TABLE IF NOT EXISTS teldrive.files (
|
||||
id text NOT NULL DEFAULT teldrive.generate_uid(16) PRIMARY KEY,
|
||||
"name" text NOT NULL,
|
||||
"type" text NOT NULL,
|
||||
mime_type text NOT NULL,
|
||||
"path" text,
|
||||
"size" bigint,
|
||||
starred bool NOT NULL,
|
||||
"depth" int,
|
||||
user_id bigint NOT NULL,
|
||||
parent_id text,
|
||||
status text DEFAULT 'active'::text,
|
||||
channel_id bigint,
|
||||
parts jsonb,
|
||||
created_at timestamp NOT NULL DEFAULT timezone('utc'::text, now()),
|
||||
updated_at timestamp NOT NULL DEFAULT timezone('utc'::text, now())
|
||||
);
|
||||
|
||||
CREATE TABLE teldrive.sessions (
|
||||
CREATE TABLE IF NOT EXISTS teldrive.users (
|
||||
user_id bigint NOT NULL PRIMARY KEY,
|
||||
"name" text,
|
||||
user_name text NOT NULL,
|
||||
is_premium bool NOT NULL,
|
||||
created_at timestamptz NOT NULL DEFAULT timezone('utc'::text, now()),
|
||||
updated_at timestamptz NOT NULL DEFAULT timezone('utc'::text, now())
|
||||
);
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS teldrive.uploads (
|
||||
id text NOT NULL DEFAULT teldrive.generate_uid(16) PRIMARY KEY,
|
||||
upload_id text NOT NULL,
|
||||
"name" text NOT NULL,
|
||||
user_id bigint,
|
||||
part_no int NOT NULL,
|
||||
part_id int NOT NULL,
|
||||
total_parts int NOT NULL,
|
||||
channel_id bigint NOT NULL,
|
||||
"size" bigint NOT NULL,
|
||||
created_at timestamp DEFAULT timezone('utc'::text, now()),
|
||||
);
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS teldrive.channels (
|
||||
channel_id bigint NOT NULL PRIMARY KEY,
|
||||
channel_name text NOT NULL,
|
||||
user_id bigint NOT NULL,
|
||||
selected boolean DEFAULT false,
|
||||
FOREIGN KEY (user_id) REFERENCES teldrive.users(user_id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS teldrive.bots (
|
||||
user_id bigint NOT NULL,
|
||||
"token" text NOT NULL,
|
||||
bot_user_name text NOT NULL,
|
||||
bot_id bigint NOT NULL,
|
||||
channel_id bigint NULL,
|
||||
FOREIGN KEY (user_id) REFERENCES teldrive.users(user_id),
|
||||
CONSTRAINT btoken_user_un UNIQUE (user_id,token)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS teldrive.sessions (
|
||||
session text NOT NULL,
|
||||
user_id bigint NOT NULL,
|
||||
hash text NOT NULL,
|
||||
created_at timestamp null default timezone('utc'::text,now()),
|
||||
created_at timestamp default timezone('utc'::text,now()),
|
||||
PRIMARY KEY(session, hash),
|
||||
FOREIGN KEY (user_id) REFERENCES teldrive.users(user_id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS name_numeric_idx ON teldrive.files USING btree (name COLLATE "numeric" NULLS FIRST);
|
||||
CREATE INDEX IF NOT EXISTS name_search_idx ON teldrive.files USING gin (teldrive.get_tsvector(name), updated_at);
|
||||
CREATE INDEX IF NOT EXISTS parent_idx ON teldrive.files USING btree (parent_id);
|
||||
CREATE INDEX IF NOT EXISTS parent_name_numeric_idx ON teldrive.files USING btree (parent_id, name COLLATE "numeric" DESC);
|
||||
CREATE INDEX IF NOT EXISTS path_idx ON teldrive.files USING btree (path);
|
||||
CREATE INDEX IF NOT EXISTS starred_updated_at_idx ON teldrive.files USING btree (starred, updated_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS status_idx ON teldrive.files USING btree (status);
|
||||
CREATE UNIQUE IF NOT EXISTS INDEX unique_file ON teldrive.files USING btree (name, parent_id, user_id) WHERE (status = 'active'::text);
|
||||
CREATE INDEX IF NOT EXISTS user_id_idx ON teldrive.files USING btree (user_id);
|
||||
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose Down
|
||||
-- +goose StatementBegin
|
||||
|
||||
DROP INDEX IF EXISTS name_numeric_idx ;
|
||||
DROP INDEX IF EXISTS name_search_idx ;
|
||||
DROP INDEX IF EXISTS parent_idx ;
|
||||
DROP INDEX IF EXISTS parent_name_numeric_idx ;
|
||||
DROP INDEX IF EXISTS path_idx ;
|
||||
DROP INDEX IF EXISTS starred_updated_at_idx ;
|
||||
DROP INDEX IF EXISTS status_idx ;
|
||||
DROP UNIQUE IF EXISTS INDEX unique_file;
|
||||
DROP INDEX IF EXISTS user_id_idx;
|
||||
|
||||
DROP TABLE IF EXISTS teldrive.files;
|
||||
DROP TABLE IF EXISTS teldrive.uploads;
|
||||
DROP TABLE IF EXISTS teldrive.users;
|
||||
DROP TABLE IF EXISTS teldrive.channels;
|
||||
DROP TABLE IF EXISTS teldrive.bots;
|
||||
DROP TABLE IF EXISTS teldrive.sessions;
|
||||
-- +goose StatementEnd
|
||||
|
|
|
@ -1,6 +1,112 @@
|
|||
-- +goose Up
|
||||
-- +goose StatementBegin
|
||||
|
||||
CREATE OR REPLACE PROCEDURE teldrive.update_size() LANGUAGE PLPGSQL AS $$
|
||||
DECLARE
|
||||
rec RECORD;
|
||||
total_size BIGINT;
|
||||
BEGIN
|
||||
FOR rec IN
|
||||
SELECT id
|
||||
FROM files
|
||||
WHERE type = 'folder'
|
||||
ORDER BY depth DESC
|
||||
LOOP
|
||||
total_size := (
|
||||
SELECT SUM(size) AS total_size
|
||||
FROM teldrive.files
|
||||
WHERE parent_id = rec.id
|
||||
);
|
||||
|
||||
UPDATE teldrive.files
|
||||
SET size = total_size
|
||||
WHERE id = rec.id;
|
||||
END LOOP;
|
||||
END;
|
||||
$$;
|
||||
|
||||
|
||||
CREATE OR REPLACE PROCEDURE teldrive.delete_files(IN file_ids TEXT[], IN op TEXT DEFAULT 'bulk') LANGUAGE PLPGSQL AS $$
|
||||
DECLARE
|
||||
rec RECORD;
|
||||
BEGIN
|
||||
IF op = 'bulk' THEN
|
||||
FOR rec IN
|
||||
SELECT id, type
|
||||
FROM teldrive.files
|
||||
WHERE id = ANY (file_ids)
|
||||
LOOP
|
||||
IF rec.type = 'folder' THEN
|
||||
CALL teldrive.delete_files(ARRAY[rec.id], 'single');
|
||||
END IF;
|
||||
|
||||
DELETE FROM teldrive.files
|
||||
WHERE id = rec.id;
|
||||
END LOOP;
|
||||
ELSE
|
||||
FOR rec IN
|
||||
SELECT id, type
|
||||
FROM teldrive.files
|
||||
WHERE parent_id = file_ids[1]
|
||||
LOOP
|
||||
IF rec.type = 'folder' THEN
|
||||
CALL teldrive.delete_files(ARRAY[rec.id], 'single');
|
||||
END IF;
|
||||
|
||||
DELETE FROM teldrive.files
|
||||
WHERE id = rec.id;
|
||||
END LOOP;
|
||||
END IF;
|
||||
END;
|
||||
$$;
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION teldrive.create_directories(
|
||||
IN tg_id BIGINT,
|
||||
IN long_path TEXT
|
||||
) RETURNS SETOF teldrive.files AS $$
|
||||
DECLARE
|
||||
path_parts TEXT[];
|
||||
current_directory_id TEXT;
|
||||
new_directory_id TEXT;
|
||||
directory_name TEXT;
|
||||
path_so_far TEXT;
|
||||
depth_dir INTEGER;
|
||||
BEGIN
|
||||
path_parts := string_to_array(regexp_replace(long_path, '^/+', ''), '/');
|
||||
|
||||
path_so_far := '';
|
||||
depth_dir := 0;
|
||||
|
||||
SELECT id INTO current_directory_id
|
||||
FROM teldrive.files
|
||||
WHERE parent_id = 'root' AND user_id = tg_id;
|
||||
|
||||
FOR directory_name IN SELECT unnest(path_parts) LOOP
|
||||
path_so_far := CONCAT(path_so_far, '/', directory_name);
|
||||
depth_dir := depth_dir + 1;
|
||||
|
||||
SELECT id INTO new_directory_id
|
||||
FROM teldrive.files
|
||||
WHERE parent_id = current_directory_id
|
||||
AND "name" = directory_name
|
||||
AND "user_id" = tg_id;
|
||||
|
||||
IF new_directory_id IS NULL THEN
|
||||
INSERT INTO teldrive.files ("name", "type", mime_type, parent_id, "user_id", starred, "depth", "path")
|
||||
VALUES (directory_name, 'folder', 'teldrive/folder', current_directory_id, tg_id, false, depth_dir, path_so_far)
|
||||
RETURNING id INTO new_directory_id;
|
||||
END IF;
|
||||
|
||||
current_directory_id := new_directory_id;
|
||||
END LOOP;
|
||||
|
||||
RETURN QUERY SELECT * FROM teldrive.files WHERE id = current_directory_id;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION teldrive.split_path(path text, OUT parent text, OUT base text) AS $$
|
||||
BEGIN
|
||||
IF path = '/' THEN
|
||||
|
@ -84,8 +190,6 @@ BEGIN
|
|||
END;
|
||||
$$;
|
||||
|
||||
drop function if exists teldrive.move_directory;
|
||||
|
||||
CREATE OR REPLACE FUNCTION teldrive.move_directory(src text, dest text,u_id bigint) RETURNS VOID AS $$
|
||||
DECLARE
|
||||
src_parent TEXT;
|
||||
|
@ -126,11 +230,33 @@ BEGIN
|
|||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION teldrive.account_stats(
|
||||
IN u_id BIGINT
|
||||
) RETURNS TABLE (total_size BIGINT, total_files BIGINT, ch_id BIGINT,ch_name TEXT ) AS $$
|
||||
DECLARE
|
||||
total_size BIGINT;
|
||||
total_files BIGINT;
|
||||
ch_id BIGINT;
|
||||
ch_name TEXT;
|
||||
BEGIN
|
||||
SELECT COUNT(*), SUM(size) into total_files,total_size FROM teldrive.files WHERE user_id=u_id AND type= 'file' and status='active';
|
||||
SELECT channel_id ,channel_name into ch_id,ch_name FROM teldrive.channels WHERE selected=TRUE AND user_id=u_id;
|
||||
RETURN QUERY SELECT total_size,total_files,ch_id,ch_name;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose Down
|
||||
-- +goose StatementBegin
|
||||
drop function if exists teldrive.split_path;
|
||||
drop function if exists teldrive.update_folder;
|
||||
drop function if exists teldrive.move_directory;
|
||||
DROP PROCEDURE IF EXISTS teldrive.update_size;
|
||||
DROP PROCEDURE IF EXISTS teldrive.delete_files;
|
||||
DROP FUNCTION IF EXISTS teldrive.create_directories;
|
||||
DROP FUNCTION IF EXISTS teldrive.split_path;
|
||||
DROP FUNCTION IF EXISTS teldrive.update_folder;
|
||||
DROP FUNCTION IF EXISTS teldrive.move_directory;
|
||||
DROP FUNCTION IF EXISTS teldrive.account_stats;
|
||||
-- +goose StatementEnd
|
||||
|
|
|
@ -114,7 +114,7 @@ func getBotInfo(ctx context.Context, token string) (*BotInfo, error) {
|
|||
|
||||
func getTGMessages(ctx context.Context, client *telegram.Client, parts []schemas.Part, channelId int64, userID string) (*tg.MessagesChannelMessages, error) {
|
||||
|
||||
ids := funk.Map(parts, func(part models.Part) tg.InputMessageClass {
|
||||
ids := funk.Map(parts, func(part schemas.Part) tg.InputMessageClass {
|
||||
return tg.InputMessageClass(&tg.InputMessageID{ID: int(part.ID)})
|
||||
})
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 82ff775d8c7a6d2620b4113a09d8a78ee4f9519f
|
||||
Subproject commit f5e563e9b3a66bcb9779d9af782ee6f9767c86d3
|
Loading…
Reference in a new issue