api changes

This commit is contained in:
divyam234 2023-12-03 02:53:06 +05:30
parent 8ee3e8b846
commit b040eb9e1e
22 changed files with 284 additions and 428 deletions

View file

@ -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

View file

@ -9,6 +9,9 @@ before:
builds:
- env:
- CGO_ENABLED=0
main:
- cmd/teldrive/main.go
flags:
- -trimpath
ldflags:

2
.vscode/launch.json vendored
View file

@ -9,7 +9,7 @@
"type": "go",
"request": "launch",
"mode": "auto",
"program": "main.go"
"program": "cmd/teldrive/main.go"
}
]
}

View file

@ -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)

View file

@ -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
View file

@ -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
View file

@ -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=

View file

@ -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))
}

View file

@ -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()
}

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -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');

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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;

View file

@ -1,3 +0,0 @@
-- +goose Up
ALTER TABLE teldrive.uploads ADD COLUMN user_id BIGINT;

View file

@ -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

View file

@ -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

View file

@ -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