Skip to content

Commit

Permalink
some kind of update
Browse files Browse the repository at this point in the history
  • Loading branch information
flameshikari committed Sep 5, 2024
1 parent bbe5bc6 commit 9cfdb43
Show file tree
Hide file tree
Showing 15 changed files with 229 additions and 173 deletions.
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.git*
Binary file added .github/assets/opengraph.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
91 changes: 58 additions & 33 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,33 +1,58 @@
name: Build

on:
push:
workflow_dispatch:

jobs:
build:
runs-on: ubuntu-latest
steps:

- name: Checkout
uses: actions/checkout@master

# - name: Setup QEMU
# uses: docker/setup-qemu-action@v1

- name: Setup Docker Buildx
uses: docker/setup-buildx-action@v1

- name: Login to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ vars.USERNAME }}
password: ${{ secrets.DOCKER_HUB_TOKEN }}

- name: Build image
uses: docker/build-push-action@v2
with:
context: .
# platforms: ${{ vars.PLATFORMS }}
push: true
tags: ${{ vars.USERNAME }}/${{ vars.REPOSITORY }}:latest
name: Build

on:
push:
branches:
- master
paths:
- .github
- Dockerfile
- package.json
- src
workflow_dispatch:

jobs:
build:
name: Build
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout Repository
uses: actions/checkout@v4

- name: Setup Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Login to the GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.TOKEN }}

- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ github.actor }}
password: ${{ secrets.DOCKER_TOKEN }}

- name: Extract Metadata
id: meta
uses: docker/metadata-action@v5
with:
images: |
${{ github.repository }}
ghcr.io/${{ github.repository }}
tags: type=raw,value=latest

- name: Build Image
uses: docker/build-push-action@v6
with:
cache-from: type=gha
cache-to: type=gha,mode=max
context: .
platforms: linux/amd64,linux/arm64,linux/arm/v7
push: true
tags: ${{ steps.meta.outputs.tags }}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
docker-compose.yml
node_modules
package-lock.json
6 changes: 3 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ FROM node:alpine AS base
WORKDIR /app

FROM base AS install
COPY --chown=node src/package.json /app
RUN npm install
COPY --chown=node package.json /app
RUN npm install --no-package-lock

FROM base AS release
COPY --chown=node --from=install /app .
COPY --chown=node src/ .
USER node
CMD node index.js
CMD npm run --silent start:docker
27 changes: 24 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
# Usage
<img src="./.github/assets/opengraph.png">

Imagine we have a Yandex.Disk link `https://disk.yandex.ru/d/0gRKgtGjqWil4g` and this service serving at `localhost:3000`. You need to cut off `https://disk.yandex.ru` from URL and append it to `localhost:3000`. Final URL will be `localhost:3000/d/0gRKgtGjqWil4g`
# ℹ️ Description

It's better to host it on the server with `disk` subdomain, like `disk.example.com`, so you can just change domain from `disk.yandex.ru` to `disk.example.com` and this service will redirect to file downloading on execution.
The service allows you to receive direct links to download a file/folder from [Yandex.Disk](https://disk.yandex.ru).

The idea is hosting this service on `disk` subdomain with any reverse proxy server. For example:
- you have this service accessible at [`disk.hexed.pw`](https://disk.hexed.pw)
- you have non-direct link [`disk.yandex.ru/d/0gRKgtGjqWil4g`](https://disk.yandex.ru/d/0gRKgtGjqWil4g)

All you had to do is replace `yandex.ru` to `hexed.pw` (will be [`disk.hexed.pw/d/0gRKgtGjqWil4g`](https://disk.hexed.pw/d/0gRKgtGjqWil4g)), then after pressing Enter the file/folder will start the downloading immediatly.

By the way the service has the frontend just in case.

## 🐳 Docker

Available in <a href="https://github.com/flameshikari/yadirect/pkgs/container/yadirect">GHCR</a> and <a href="https://hub.docker.com/r/flameshikari/yadirect">Docker Hub</a> for multiple platforms.

```yaml
services:
yadirect:
image: flameshikari/yadirect
container_name: yadirect
ports:
- 3000:3000
```
9 changes: 0 additions & 9 deletions docker-compose.yml

This file was deleted.

9 changes: 6 additions & 3 deletions src/package.json → package.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
{
"name": "Yadirect",
"name": "yadirect",
"version": "1.0.0",
"type": "module",
"author": "flameshikari",
"license": "MIT",
"scripts": {
"start": "node src/index.js",
"start:docker": "node index.js"
},
"dependencies": {
"apicache": "^1.6.3",
"cors": "^2.8.5",
"express": "^4.19.2",
"helmet": "^7.1.0",
"node-fetch": "^3.3.2",
"node-fetch-cache": "^4.1.0"
"node-fetch-cache": "^5.0.2"
}
}
92 changes: 51 additions & 41 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,50 +1,60 @@
#!/usr/bin/env node

import apicache from 'apicache'
import cors from 'cors'
import express from 'express'
import helmet from 'helmet'
import cors from 'cors';
import express from 'express';
import helmet from 'helmet';

import NodeFetchCache, { MemoryCache } from 'node-fetch-cache'
import NodeFetchCache, { MemoryCache } from 'node-fetch-cache';

const app = express()
const router = express.Router()
const port = 3000

const app = express();
const router = express.Router();
const port = 3000;
const fetch = NodeFetchCache.create({
cache: new MemoryCache({ ttl: 60000 }),
shouldCacheResponse: (response) => response.ok,
})


router.get('/*', async (req, res, next) => {
const regexp = /([di])\/(\w+)\/?(.*)?/
const match = req.originalUrl.match(regexp)
const type = match[1]
const hash = match[2]
const path = match[3] ? `path=/${match[3]}&` : ''
const publicKeyUrl = `https://disk.yandex.ru/${type}/${hash}`
const redirectUrl = `https://cloud-api.yandex.net/v1/disk/public/resources/download?${path}public_key=${publicKeyUrl}`
const response = await fetch(redirectUrl)
const result = await response.json()
if (response.ok) {
res.redirect(result.href)
} else {
res.send(result)
}
})

app.set('json spaces', 2)
app.set('x-powered-by', false)
cache: new MemoryCache({ ttl: 60000 }),
shouldCacheResponse: (response) => response.ok,
});


router.get(/([di])\/(\w+)\/?(.*)?/, async (req, res, next) => {
try {
const regexp = /([di])\/(\w+)\/?(.*)?/;
const match = req.originalUrl.match(regexp);
const type = match[1];
const hash = match[2];
const path = match[3] ? `path=/${match[3]}&` : '';
const publicKeyUrl = `https://disk.yandex.ru/${type}/${hash}`;
const redirectUrl = `https://cloud-api.yandex.net/v1/disk/public/resources/download?${path}public_key=${publicKeyUrl}`;
const response = await fetch(redirectUrl);
const result = await response.json();
if (response.ok) {
res.redirect(result.href);
} else {
res.json(result);
};
} catch(e) {
res.redirect('/');
};
});

router.all('*', (req, res) => {
res.redirect('/');
});


app.set('json spaces', 2);
app.set('x-powered-by', false);

app.use(
cors(),
helmet({ contentSecurityPolicy: false, xDownloadOptions: false }),
express.urlencoded({ extended: false }),
express.json(),
express.static('public'),
router,
)
cors(),
helmet({ contentSecurityPolicy: false, xDownloadOptions: false }),
express.urlencoded({ extended: false }),
express.json(),
express.static('./public'),
router,
);


app.listen(port, () => {
console.log(`listening at ${port}/tcp`)
})
console.log(`listening at ${port}/tcp`);
});
2 changes: 1 addition & 1 deletion src/public/favicon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/public/font.woff2
Binary file not shown.
34 changes: 18 additions & 16 deletions src/public/index.html
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
<!doctype html>
<html>
<head>
<title>Yadirect</title>
<meta charset="utf-8"/>
<link rel="icon" type="image/x-icon" href="favicon.svg">
<link href="style.css" rel="stylesheet"/>
</head>
<body>
<div class="container">
<a href="https://github.com/flameshikari/yadirect">
<img src="logo.svg" alt="Logo">
</a>
<input autofocus id="text" type="text" placeholder="https://disk.yandex.ru/...">
<span class="note"></span>
</div>
<script src="script.js"></script>
</body>
<head>
<title>Yadirect</title>
<meta charset="utf-8"/>
<link rel="icon" type="image/x-icon" href="favicon.svg">
<link href="style.css" rel="stylesheet"/>
</head>
<body>
<div class="container">
<a href="https://github.com/flameshikari/yadirect">
<span class="title">
<font color="ff0000">Y</font><font color="ffffff">adirect</font>
</span>
</a>
<input autofocus id="text" type="text" placeholder="https://disk.yandex.ru/...">
<span class="note"></span>
</div>
<script src="script.js"></script>
</body>
</html>
1 change: 0 additions & 1 deletion src/public/logo.svg

This file was deleted.

33 changes: 15 additions & 18 deletions src/public/script.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
const correctUrl = (url) => url.replace(/(?<!:)\/+/gm, '/')
const text = document.querySelector('#text');

const correctUrl = (url) => url.replace(/^(https?:\/\/)?.*disk.yandex.ru\//gm, '/');

const rootDomain = (hostname) => {
let parts = hostname.split('.')
if (parts.length <= 2) return hostname
let parts = hostname.split('.');
if (parts.length <= 2) return hostname;
parts = parts.slice(-3);
return parts.slice(-2).join('.')
}

if (window.location.pathname != '/') window.location.href = '/'

const domain = rootDomain(window.location.hostname) + (window.location.port == '' ? '' : `:${window.location.port}`)
return parts.slice(-2).join('.');
};

document.querySelector('.note').innerText = `or change 'yandex.ru' to '${domain}' in URL`
const domain = rootDomain(window.location.hostname) + (window.location.port == '' ? '' : `:${window.location.port}`);

document.querySelector('#text').addEventListener('keypress', (event) => {
if (event.key === 'Enter') {
const text = document.querySelector('#text')
const url = correctUrl(`/${text.value.trim()}`)
text.value = ''
window.location.href = url
}
})
text.addEventListener('keypress', (event) => {
if (event.key === 'Enter') {
const url = correctUrl(`/${text.value.trim()}`);
text.value = '';
window.location.href = url;
};
});
Loading

0 comments on commit 9cfdb43

Please sign in to comment.