90 Commits

Author SHA1 Message Date
Dima yawaflua Andreev 83c7fc1723 Merge pull request #4 from yawaflua/yawaflua-patch-1
Удаление призыва к голосу
2024-01-21 23:25:49 +03:00
Dima yawaflua Andreev 5e966809b0 Удаление призыва к голосу 2024-01-21 23:24:50 +03:00
Dima yawaflua Andreev dd4a2798c4 Update _Layout.cshtml 2024-01-21 01:37:07 +03:00
Дмитрий Шиманский 152b5d8812 add page redirector for chorten-url service, u can use this feature, using this route: DOMAIN/?uri=SHORTED_URI
fix backend controller and change route to DOMAIN/r/SHORTED_URI
2024-01-17 11:51:53 +03:00
Dima yawaflua Andreev 87e1f51e08 Update README.md 2024-01-11 14:04:25 +03:00
Dima yawaflua Andreev ab6180b0d2 Update README.md 2024-01-11 14:02:12 +03:00
Дмитрий Шиманский 89f1ab0b85 add .Join function for debug message 2024-01-11 13:55:02 +03:00
Dima yawaflua Andreev 75c8f58544 Merge pull request #3 from yawaflua/yawaflua-debug-2612
merge branches
2024-01-11 13:49:57 +03:00
Дмитрий Шиманский eded562b7e set poster to backend from public to try function 2024-01-11 13:48:53 +03:00
Дмитрий Шиманский c8e877402c hotfix 2024-01-11 13:44:22 +03:00
Дмитрий Шиманский f1f635a520 add writing exception in console 2024-01-11 13:41:31 +03:00
Dima yawaflua Andreev 62e030436a Update README.md 2024-01-03 21:04:43 +03:00
Dima yawaflua Andreev a83b2169f7 Merge pull request #2 from yawaflua/yawaflua-debug-2612
Merge branches
2023-12-26 13:25:02 +03:00
Дмитрий Шиманский e2800cfc2e some code review 2023-12-26 13:23:30 +03:00
Dima yawaflua Andreev 05d5f8291c Update dotnet.yml 2023-12-26 13:20:39 +03:00
Дмитрий Шиманский b9036e2165 hotfix redirect system
add auth to create posts and redirects
2023-12-26 13:16:03 +03:00
Дмитрий Шиманский 38c12ca246 Add caching all data from backend and change getting readme data from page(Index.cshtml) to api(HomeController.cs) with cache readme file 2023-12-24 23:02:08 +03:00
Дмитрий Шиманский 153979cbbd bugfix 2023-12-23 23:19:22 +03:00
Dima yawaflua 8df7e26494 Update README.md 2023-12-23 02:22:46 +03:00
Дмитрий Шиманский 8c88eea1d7 optimize code 2023-12-23 00:11:03 +03:00
Дмитрий Шиманский 01cd487a0d try to fix using string[] 2023-12-23 00:07:18 +03:00
Дмитрий Шиманский 799e435afc ooops, fix bool logic 2023-12-23 00:02:24 +03:00
Dima yawaflua 0dc93500c8 Update README.md 2023-12-22 23:59:14 +03:00
Дмитрий Шиманский 782dea8c9d fix author url
add many ownersid
2023-12-22 23:54:50 +03:00
Дмитрий Шиманский f79e10f148 fix adminpanel.js 2023-12-22 23:13:20 +03:00
Дмитрий Шиманский ba514f8bca setting up logging in controller 2023-12-22 23:06:28 +03:00
Дмитрий Шиманский d410c11f6f set replace " to \" and newline to "\\n" 2023-12-22 22:57:55 +03:00
Dima yawaflua a91de6921f Update .dockerignore 2023-12-22 22:48:10 +03:00
Дмитрий Шиманский b91582a374 Fix AdminPanel json 2023-12-22 21:37:18 +03:00
Dima yawaflua ede506cb5d Update README.md 2023-12-21 09:26:56 +03:00
Dima yawaflua 6b4f63c376 Update README.md 2023-12-21 09:26:28 +03:00
Dima yawaflua 9000b9c372 Update README.md 2023-12-21 00:53:10 +03:00
Дмитрий Шиманский 408f7525f1 try to hotfix "invalid client" error from discord 2023-12-21 00:11:10 +03:00
Дмитрий Шиманский f7f5723b2d hotfix discord auth url 2023-12-21 00:04:04 +03:00
Дмитрий Шиманский 921b8f3db3 add environ error message
add to environ some data and some codereview pages
some fix oembed and OpenGraph
2023-12-20 23:58:14 +03:00
Dima yawaflua 8a73f597cf Update README.md 2023-12-20 23:10:41 +03:00
Dima yawaflua 8a879b69f0 Update README.md 2023-12-20 09:54:23 +03:00
Дмитрий Шиманский a1d06708f0 finally fix environ 2023-12-20 09:39:20 +03:00
Дмитрий Шиманский fa82a26828 also try 2023-12-20 09:34:37 +03:00
Дмитрий Шиманский 5c9f9fc1c8 environ test 2023-12-20 09:28:29 +03:00
Дмитрий Шиманский 4d665665c1 fix env 2023-12-20 09:26:18 +03:00
Дмитрий Шиманский 1593ea8d5e try to use environment 2023-12-20 09:21:48 +03:00
Дмитрий Шиманский 25308408f9 try to use environmnents 2023-12-19 21:24:18 +03:00
Дмитрий Шиманский ed292bfe21 try to fix env in dockerfile 2023-12-19 21:08:56 +03:00
Дмитрий Шиманский 93220d9d79 add connetction string to docker args 2023-12-19 20:50:27 +03:00
Дмитрий Шиманский 09bcf505cb add args parser 2023-12-19 20:24:29 +03:00
Дмитрий Шиманский a690cd5b40 change files to publish 2023-12-19 20:24:28 +03:00
Дмитрий Шиманский d3aac3ccbf add script loader 2023-12-19 18:47:08 +03:00
Дмитрий Шиманский 964326ec3b fix oembed 2023-12-19 18:40:02 +03:00
Дмитрий Шиманский 179584620f hotfix time 2023-12-19 18:36:12 +03:00
Дмитрий Шиманский 967e08c57a WTH LAST HOTFIX 2023-12-19 18:31:43 +03:00
Дмитрий Шиманский 3413c74bb3 try to fix 2023-12-19 18:27:25 +03:00
Дмитрий Шиманский 2d705ce601 hotfix 2023-12-19 17:44:18 +03:00
Дмитрий Шиманский 43520544ed change int to ulong discord id 2023-12-19 17:36:55 +03:00
Дмитрий Шиманский 4d086ae1e4 hotfix 2023-12-19 17:29:15 +03:00
Дмитрий Шиманский aaefcea154 remove nonusable method 2023-12-19 17:25:49 +03:00
Дмитрий Шиманский 36d4b07e0e hotfix 2023-12-19 17:24:26 +03:00
Дмитрий Шиманский f8ff067789 create appsettings 2023-12-19 16:28:20 +03:00
Dima yawaflua 3743e3f1af Update .gitignore 2023-12-19 12:16:54 +03:00
Dima yawaflua 3c055d5fb4 Update Startup.cs 2023-12-19 12:08:57 +03:00
Dima yawaflua 7de7a23024 Update Dockerfile 2023-12-19 12:07:08 +03:00
Dima yawaflua 5759241313 Update dotnet.yml 2023-12-19 12:05:23 +03:00
Dima yawaflua 0f6c637e3e Update yaflay.ru.csproj 2023-12-19 12:01:34 +03:00
Дмитрий Шиманский a5d39384ac pooko 2023-12-19 11:57:37 +03:00
Dima yawaflua 4e43b1631b Update docker-image.yml 2023-12-19 11:36:55 +03:00
Дмитрий Шиманский 14d045107f add blogs, redirects
set admin-panel
2023-12-19 11:36:19 +03:00
Дмитрий Шиманский d2fe5665b7 change toast color and some fixes 2023-11-27 17:28:38 +03:00
Дмитрий Шиманский ac77c00a7f fix very big picture with stats 2023-11-26 21:12:02 +03:00
Дмитрий Шиманский 634dde37a2 Merge branch 'master' of https://github.com/YaFlay/yaflay.ru 2023-11-10 17:39:41 +03:00
Дмитрий Шиманский e6d084f78c change yaflay.ru to yawaflua.ru in oembed and add pushup message 2023-11-10 17:39:38 +03:00
Dima yawaflua 828aebea08 Update redirect_uris.json 2023-11-08 10:44:22 +03:00
Дмитрий Шиманский a4bd0eba1a ok change my nickname. Again... 2023-11-06 22:52:01 +03:00
Дмитрий Шиманский c892e0f1aa change my nickname 2023-11-06 22:51:05 +03:00
Дмитрий Шиманский 7be291d017 Merge branch 'master' of https://github.com/YaFlay/yaflay.ru 2023-11-06 22:20:31 +03:00
Дмитрий Шиманский 256c3c10d4 fix memory crashing 2023-11-06 21:58:03 +03:00
Dima YaFlay 2e023a2f13 Update README.md 2023-10-26 21:21:40 +03:00
Dima YaFlay 76b444f3ff Update docker-image.yml 2023-10-26 11:54:31 +03:00
Dima YaFlay 7894fec88e Update README.md 2023-10-26 11:54:12 +03:00
Дмитрий Шиманский d31d65c59d hotfix!
Change uri of statics
2023-10-22 17:17:07 +03:00
Дмитрий Шиманский ed26d52da8 change favicon and not found page 2023-10-22 17:10:57 +03:00
Дмитрий Шиманский 35368f4d7c Make 500 Error page 2023-10-22 17:02:30 +03:00
Дмитрий Шиманский 76208767b2 Add 404 page
Some rework Robots.txt
BugFixes controllers
2023-10-22 15:44:06 +03:00
Дмитрий Шиманский e4537fe81e some rework oembed and opengraph metadata 2023-10-22 14:12:38 +03:00
Дмитрий Шиманский c0f29b4f86 Merge branch 'master' of https://github.com/YaFlay/yaflay.ru 2023-10-22 14:03:37 +03:00
Дмитрий Шиманский 75d9ce238e bugfix 2023-10-22 14:03:00 +03:00
Dima YaFlay 4017486877 Update docker-image.yml 2023-10-22 13:58:33 +03:00
Dima YaFlay 5aaf88c75e Delete dockerio from packages 2023-10-22 13:55:45 +03:00
Dima YaFlay 3b5553e3f9 Update docker-image.yml 2023-10-22 13:54:16 +03:00
Дмитрий Шиманский 848befc29a bugfix 2023-10-22 13:53:05 +03:00
Дмитрий Шиманский 24bb5cf21a add opengraph 2023-10-22 13:29:29 +03:00
62 changed files with 3907 additions and 146 deletions
-1
View File
@@ -22,4 +22,3 @@
**/secrets.dev.yaml
**/values.dev.yaml
LICENSE
README.md
+4
View File
@@ -0,0 +1,4 @@
[*.cs]
# CS8602: Разыменование вероятной пустой ссылки.
dotnet_diagnostic.CS8602.severity = none
+2 -4
View File
@@ -4,9 +4,8 @@ on:
release:
types: [published]
push:
types: [latest]
pull_request:
types: [latest]
branches: [ "master" ]
jobs:
push_to_registries:
@@ -37,7 +36,6 @@ jobs:
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
with:
images: |
yaflay/yaflay.ru
ghcr.io/${{ github.repository }}
- name: Build and push Docker images
+3 -3
View File
@@ -5,9 +5,9 @@ name: .NET
on:
push:
branches: [ "master" ]
branches: [ "*" ]
pull_request:
branches: [ "master" ]
branches: [ "*" ]
jobs:
build:
@@ -19,7 +19,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: 6.0.x
dotnet-version: 7.0.x
- name: Restore dependencies
run: dotnet restore
- name: Build
+1
View File
@@ -361,3 +361,4 @@ MigrationBackup/
# Fody - auto-generated XML schema
FodyWeavers.xsd
/appsettings.json
+73
View File
@@ -0,0 +1,73 @@
using System.Security.Claims;
using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Options;
using yaflay.ru.Database.Tables;
using yaflay.ru.Models;
using yaflay.ru.Models.Tables;
namespace yaflay.ru.Auth;
public class ApiKeyAuthantication : AuthenticationHandler<AuthenticationSchemeOptions>
{
private AppDbContext ctx;
private IMemoryCache cache;
public ApiKeyAuthantication(
IOptionsMonitor<AuthenticationSchemeOptions> options,
ILoggerFactory logger,
UrlEncoder encoder,
ISystemClock clock,
AppDbContext ctx,
IMemoryCache cache
) : base(options, logger, encoder, clock)
{
this.ctx = ctx;
this.cache = cache;
}
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
if (!Request.Headers.TryGetValue("Authorization", out var apiKeyHeaderValues))
return AuthenticateResult.Fail("API Key was not provided.");
string? providedApiKey = apiKeyHeaderValues.FirstOrDefault()?.Replace("Bearer ", "");
Console.WriteLine("APIKEY: " + providedApiKey);
if (FindApiKey(providedApiKey, out ApiKey? apiKey))
{
var claims = new[]
{
new Claim("Bearer", apiKey.Type.ToString())
};
var identity = new ClaimsIdentity(claims, Scheme.Name);
var principal = new ClaimsPrincipal(identity);
var ticket = new AuthenticationTicket(principal, Scheme.Name);
return AuthenticateResult.Success(ticket);
}
Console.WriteLine("im there");
return AuthenticateResult.Fail("Invalid API Key provided.");
}
private bool FindApiKey(string? providedApiKey, out ApiKey? apiKey)
{
var fromCache = cache.Get<ApiKey>($"apiKey-{providedApiKey}");
if (fromCache == null)
{
Console.WriteLine($"Im there: {fromCache}, {providedApiKey}");
apiKey = ctx.ApiKeys.Find(providedApiKey);
if (apiKey != null)
{
cache.Set($"apiKey-{providedApiKey}", (object)apiKey, DateTime.Now.AddMinutes(10));
}
}
else
{
apiKey = fromCache;
}
return ctx.ApiKeys.Any(k => k.Key == providedApiKey);
}
}
+9
View File
@@ -0,0 +1,9 @@
namespace yaflay.ru.Auth
{
public enum ApiKeyTypes
{
Public,
Private
}
}
+240 -30
View File
@@ -1,47 +1,257 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.RateLimiting;
using System.Text.Json;
using System.Text.Json.Nodes;
using yaflay.ru.Models.Tables;
using Microsoft.Extensions.Caching.Memory;
using yaflay.ru.Models;
using System;
using Microsoft.AspNetCore.Authorization;
using yaflay.ru.Auth;
using yaflay.ru.Database.Tables;
namespace yaflay.ru.Новая_папка
namespace yaflay.ru.Controllers
{
[Route("")]
public class HomeController : Controller
{
// GET: HomeController
private async Task<string> getUrlFromGit(string baseUrl)
private IMemoryCache cache;
private AppDbContext ctx;
public HomeController(IMemoryCache cache, AppDbContext ctx)
{
try
{
HttpClient client = new();
HttpResponseMessage getter = await client.GetAsync("https://raw.githubusercontent.com/YaFlay/yaflay.ru/master/redirect_uris.json");
await Console.Out.WriteLineAsync(await getter.Content.ReadAsStringAsync());
JsonNodeOptions jsonNodeOptions = new ();
JsonDocumentOptions jsonDocumentOptions = new();
jsonDocumentOptions.AllowTrailingCommas = true;
JsonNode allFile = JsonNode.Parse(await getter.Content.ReadAsStringAsync(), jsonNodeOptions, jsonDocumentOptions);
return (string?)allFile[baseUrl];
}
catch (Exception except)
{
await Console.Out.WriteLineAsync(except.ToString());
return null;
}
this.cache = cache;
this.ctx = ctx;
}
public class authorizeBody
{
public string melon { get; set; }
public string watermelon { get; set; }
public string discordId { get; set; }
public ApiKeyTypes type { get; set; }
}
public class commentBody
{
public string text { get; set; }
public string sender { get; set; }
}
public class articleBody
{
public string title { get; set; }
public string annotation { get; set; }
public string text { get; set; }
public string image { get; set; }
public string author { get; set; }
}
public class redirectBody
{
public string url { get; set; }
public string uri { get; set; }
public string author { get; set; }
}
// GET: HomeController/Details/5
[HttpGet("{uri}")]
public async Task<IActionResult> fromGitHub(string? uri)
[HttpGet("api/Index")]
public async Task<IActionResult> getIndexPage()
{
string? indexPage = cache.Get<string>($"indexPage");
if (indexPage == null)
{
indexPage = await Startup.client.GetStringAsync(Startup.readmeFile);
if (indexPage != null)
cache.Set($"indexPage", (object)indexPage, DateTime.Now.AddMinutes(10));
}
return Ok(indexPage);
}
[HttpPost("api/redirects")]
[Authorize(AuthenticationSchemes = "DISCORD-OAUTH-PRIVATE")]
public async Task<IActionResult> createRedirectUri([FromBody]redirectBody body)
{
Console.WriteLine("url" + body.uri);
HttpResponseMessage message;
using (var requestMessage =
new HttpRequestMessage(HttpMethod.Get, "https://discordapp.com/api/oauth2/@me"))
{
requestMessage.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", Request.Cookies["melon"]); ;
message = await Startup.client.SendAsync(requestMessage);
}
string responseBody = await message.Content.ReadAsStringAsync();
JsonNode response = JsonNode.Parse(responseBody);
if (response["user"] != null || Startup.ownerId?.FirstOrDefault(response["user"]?["id"].ToString()) == null)
{
Redirects redirects = new()
{
redirectTo = body.url,
uri = body.uri
};
await ctx.Redirects.AddAsync(redirects);
await ctx.SaveChangesAsync();
return Ok();
}
else
{
return Unauthorized();
}
}
[HttpPost("api/Blog")]
[Authorize(AuthenticationSchemes = "DISCORD-OAUTH-PRIVATE")]
public async Task<IActionResult> createArticle([FromBody] articleBody body)
{
HttpResponseMessage message;
using (var requestMessage =
new HttpRequestMessage(HttpMethod.Get, "https://discordapp.com/api/oauth2/@me"))
{
requestMessage.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", Request.Cookies["melon"]); ;
message = await Startup.client.SendAsync(requestMessage);
}
string responseBody = await message.Content.ReadAsStringAsync();
JsonNode response = JsonNode.Parse(responseBody);
if (response["user"] != null || Startup.ownerId?.FirstOrDefault(response["user"]?["id"].ToString()) == null )
{
try
{
Blogs article = new()
{
Annotation = body.annotation,
authorId = response["user"]["id"].ToString(),
dateTime = DateTime.Now,
ImageUrl = body.image,
Text = body.text,
Title = body.title,
authorNickname = response["user"]["global_name"].ToString()
};
await ctx.Blogs.AddAsync(article);
await ctx.SaveChangesAsync();
return Ok(body);
}
catch (Exception ex)
{
Console.WriteLine("error: HomeController error");
Console.WriteLine("debug: lines: 80-96");
Console.WriteLine($"debug: data from site: {body}");
Console.WriteLine($"debug: exception: {ex.Message}");
return StatusCode(500, body);
}
}
else
{
return Unauthorized(body);
}
}
[HttpGet("logout")]
public async Task<IActionResult> authorizeDiscord()
{
Response.Cookies.Delete("melon");
Response.Cookies.Delete("watermelon");
Response.Cookies.Delete("cable");
return Redirect("/");
}
[HttpGet("api/Blog/{blogId?}/comments")]
public async Task<IActionResult> blogComments(int? blogId)
{
Comments[]? comments = (Comments[]?)cache.Get($"commentsWithBlogId{blogId}");
if (comments == null)
{
comments = ctx.Comments.Where(k => k.postId == blogId).ToArray();
if (comments != null)
cache.Set($"commentsWithBlogId{blogId}", (object[])comments, DateTime.Now.AddMinutes(5));
}
return Ok(comments);
}
[HttpPost("api/Blog/{blogId}/comments")]
[Authorize(AuthenticationSchemes = "DISCORD-OAUTH-PUBLIC")]
public async Task<IActionResult> CreateBlogComments(int blogId, [FromBody]commentBody body)
{
Comments comment = new()
{
creatorMail = body.sender,
dateTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
Text = body.text,
postId = blogId
};
await ctx.Comments.AddAsync(comment);
await ctx.SaveChangesAsync();
return Ok();
}
[HttpGet("api/Blog/{blogId}")]
public async Task<IActionResult> blog(int blogId)
{
Blogs? blog = cache.Get<Blogs>($"blogWithId{blogId}");
if (blog == null)
{
blog = ctx.Blogs.FirstOrDefault(k => k.Id == blogId);
if (blog != null)
cache.Set($"blogWithId{blogId}", (object)blog, DateTime.Now.AddMinutes(10));
}
return Ok(blog);
}
[HttpGet("api/Blog")]
public async Task<IActionResult> allBlogs()
{
Blogs[]? blogs = cache.Get<Blogs[]>($"allBlogs");
if (blogs == null)
{
blogs = ctx.Blogs.ToArray();
if (blogs != null)
cache.Set($"allBlogs", (object)blogs, DateTime.Now.AddMinutes(10));
}
return Ok(blogs);
}
[HttpPost("api/authorize")]
public async Task<IActionResult> authorizeUser([FromBody] authorizeBody body)
{
var fromCache = cache.Get<ApiKey>($"apiKey-melon-{body.melon}");
if (fromCache == null)
{
var melon = ctx.ApiKeys.FirstOrDefault(k => k.Melon == body.melon);
if (melon != null)
{
cache.Set($"apiKey-melon-{body.melon}", (object)melon, DateTime.Now.AddMinutes(20));
}
}
await ctx.ApiKeys.AddAsync(
new()
{
DiscordOwnerId = ulong.Parse(body.discordId),
Key = body.melon,
Melon = body.melon,
Type = ApiKeyTypes.Public
}
);
await ctx.SaveChangesAsync();
return Ok(body.melon);
}
[HttpGet("r/{uri}")]
public async Task<IActionResult> FromGitHub(string uri)
{
Console.WriteLine(uri);
//if (uri == "404") { return Ok(); }
Redirects? fromCache = cache.Get<Redirects>($"redirectsWithUrl-{uri}") ?? null;
if (fromCache == null)
{
fromCache = ctx.Redirects.FirstOrDefault(k => k.uri == uri);
Console.WriteLine("Im here!");
if (fromCache != null)
cache.Set($"redirectsWithUrl-{uri}", (object)fromCache, DateTime.Now.AddMinutes(10));
}
Console.WriteLine(fromCache?.ToString());
return Redirect(fromCache?.redirectTo ?? "/404");
if (uri == "Robots.txt") { return Ok("User-Agent: * \n Disallow: /*"); }
string? url = await getUrlFromGit(uri);
await Console.Out.WriteLineAsync(url == null ? "Null" : $"notNull {url}");
return Redirect(url ?? "https://yaflay.ru/");
}
// GET: HomeController/Create
}
}
+13 -4
View File
@@ -1,11 +1,11 @@
#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
WORKDIR /src
COPY ["yaflay.ru.csproj", "."]
RUN dotnet restore "./yaflay.ru.csproj"
@@ -14,6 +14,15 @@ WORKDIR "/src/."
RUN dotnet build "yaflay.ru.csproj" -c Release -o /app/build
FROM build AS publish
ENV CLIENTID 123
ENV CLIENTSECRET aAbB
ENV REDIRECTURL http://example.org/
ENV PSQL_HOST localhost
ENV PSQL_USER root
ENV PSQL_PASSWORD root
ENV PSQL_DATABASE database
ENV OWNERID 1111111
ENV READMEFILE https://raw.githubusercontent.com/yawaflua/yawaflua/main/README.md
RUN dotnet publish "yaflay.ru.csproj" -c Release -o /app/publish /p:UseAppHost=false
FROM base AS final
+88
View File
@@ -0,0 +1,88 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using yaflay.ru.Models;
#nullable disable
namespace yaflay.ru.Migrations
{
[DbContext(typeof(AppDbContext))]
[Migration("20231127204250_Migrate271122342")]
partial class Migrate271122342
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.12")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("yaflay.ru.Models.Tables.Blogs", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Annotation")
.IsRequired()
.HasColumnType("text");
b.Property<string>("ImageUrl")
.HasColumnType("text");
b.Property<string>("Text")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("text");
b.Property<DateTime>("dateTime")
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.ToTable("Blogs", "public");
});
modelBuilder.Entity("yaflay.ru.Models.Tables.Comments", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Text")
.IsRequired()
.HasColumnType("text");
b.Property<string>("creatorMail")
.IsRequired()
.HasColumnType("text");
b.Property<long>("dateTime")
.HasColumnType("bigint");
b.Property<int>("postId")
.HasColumnType("integer");
b.HasKey("Id");
b.ToTable("Comments", "public");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,66 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace yaflay.ru.Migrations
{
/// <inheritdoc />
public partial class Migrate271122342 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.EnsureSchema(
name: "public");
migrationBuilder.CreateTable(
name: "Blogs",
schema: "public",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
Title = table.Column<string>(type: "text", nullable: false),
Text = table.Column<string>(type: "text", nullable: false),
Annotation = table.Column<string>(type: "text", nullable: false),
ImageUrl = table.Column<string>(type: "text", nullable: true),
dateTime = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Blogs", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Comments",
schema: "public",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
dateTime = table.Column<long>(type: "bigint", nullable: false),
Text = table.Column<string>(type: "text", nullable: false),
creatorMail = table.Column<string>(type: "text", nullable: false),
postId = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Comments", x => x.Id);
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Blogs",
schema: "public");
migrationBuilder.DropTable(
name: "Comments",
schema: "public");
}
}
}
+88
View File
@@ -0,0 +1,88 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using yaflay.ru.Models;
#nullable disable
namespace yaflay.ru.Migrations
{
[DbContext(typeof(AppDbContext))]
[Migration("20231204171742_Migrate04122016")]
partial class Migrate04122016
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.12")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("yaflay.ru.Models.Tables.Blogs", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Annotation")
.IsRequired()
.HasColumnType("text");
b.Property<string>("ImageUrl")
.HasColumnType("text");
b.Property<string>("Text")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("text");
b.Property<DateTime>("dateTime")
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.ToTable("Blogs", "public");
});
modelBuilder.Entity("yaflay.ru.Models.Tables.Comments", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Text")
.IsRequired()
.HasColumnType("text");
b.Property<string>("creatorMail")
.IsRequired()
.HasColumnType("text");
b.Property<long>("dateTime")
.HasColumnType("bigint");
b.Property<int>("postId")
.HasColumnType("integer");
b.HasKey("Id");
b.ToTable("Comments", "public");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,22 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace yaflay.ru.Migrations
{
/// <inheritdoc />
public partial class Migrate04122016 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
}
}
}
+109
View File
@@ -0,0 +1,109 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using yaflay.ru.Models;
#nullable disable
namespace yaflay.ru.Migrations
{
[DbContext(typeof(AppDbContext))]
[Migration("20231204210831_Migrate0512")]
partial class Migrate0512
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.12")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("yaflay.ru.Models.Tables.Blogs", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Annotation")
.IsRequired()
.HasColumnType("text");
b.Property<string>("ImageUrl")
.HasColumnType("text");
b.Property<string>("Text")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("text");
b.Property<DateTime>("dateTime")
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.ToTable("Blogs", "public");
});
modelBuilder.Entity("yaflay.ru.Models.Tables.Comments", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Text")
.IsRequired()
.HasColumnType("text");
b.Property<string>("creatorMail")
.IsRequired()
.HasColumnType("text");
b.Property<long>("dateTime")
.HasColumnType("bigint");
b.Property<int>("postId")
.HasColumnType("integer");
b.HasKey("Id");
b.ToTable("Comments", "public");
});
modelBuilder.Entity("yaflay.ru.Models.Tables.Redirects", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("redirectTo")
.IsRequired()
.HasColumnType("text");
b.Property<string>("uri")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Redirects");
});
#pragma warning restore 612, 618
}
}
}
+36
View File
@@ -0,0 +1,36 @@
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace yaflay.ru.Migrations
{
/// <inheritdoc />
public partial class Migrate0512 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Redirects",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
uri = table.Column<string>(type: "text", nullable: false),
redirectTo = table.Column<string>(type: "text", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Redirects", x => x.Id);
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Redirects");
}
}
}
+145
View File
@@ -0,0 +1,145 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using yaflay.ru.Models;
#nullable disable
namespace yaflay.ru.Migrations
{
[DbContext(typeof(AppDbContext))]
[Migration("20231218172614_Migrate18122023")]
partial class Migrate18122023
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.12")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("yaflay.ru.Models.Tables.Author", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int>("discordId")
.HasColumnType("integer");
b.Property<string>("discordNickName")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Author");
});
modelBuilder.Entity("yaflay.ru.Models.Tables.Blogs", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Annotation")
.IsRequired()
.HasColumnType("text");
b.Property<string>("ImageUrl")
.HasColumnType("text");
b.Property<string>("Text")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("text");
b.Property<int>("authorId")
.HasColumnType("integer");
b.Property<DateTime>("dateTime")
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.HasIndex("authorId");
b.ToTable("Blogs", "public");
});
modelBuilder.Entity("yaflay.ru.Models.Tables.Comments", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Text")
.IsRequired()
.HasColumnType("text");
b.Property<string>("creatorMail")
.IsRequired()
.HasColumnType("text");
b.Property<long>("dateTime")
.HasColumnType("bigint");
b.Property<int>("postId")
.HasColumnType("integer");
b.HasKey("Id");
b.ToTable("Comments", "public");
});
modelBuilder.Entity("yaflay.ru.Models.Tables.Redirects", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("redirectTo")
.IsRequired()
.HasColumnType("text");
b.Property<string>("uri")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Redirects");
});
modelBuilder.Entity("yaflay.ru.Models.Tables.Blogs", b =>
{
b.HasOne("yaflay.ru.Models.Tables.Author", "author")
.WithMany()
.HasForeignKey("authorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("author");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,74 @@
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace yaflay.ru.Migrations
{
/// <inheritdoc />
public partial class Migrate18122023 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
name: "authorId",
schema: "public",
table: "Blogs",
type: "integer",
nullable: false,
defaultValue: 0);
migrationBuilder.CreateTable(
name: "Author",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
discordId = table.Column<int>(type: "integer", nullable: false),
discordNickName = table.Column<string>(type: "text", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Author", x => x.Id);
});
migrationBuilder.CreateIndex(
name: "IX_Blogs_authorId",
schema: "public",
table: "Blogs",
column: "authorId");
migrationBuilder.AddForeignKey(
name: "FK_Blogs_Author_authorId",
schema: "public",
table: "Blogs",
column: "authorId",
principalTable: "Author",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Blogs_Author_authorId",
schema: "public",
table: "Blogs");
migrationBuilder.DropTable(
name: "Author");
migrationBuilder.DropIndex(
name: "IX_Blogs_authorId",
schema: "public",
table: "Blogs");
migrationBuilder.DropColumn(
name: "authorId",
schema: "public",
table: "Blogs");
}
}
}
+145
View File
@@ -0,0 +1,145 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using yaflay.ru.Models;
#nullable disable
namespace yaflay.ru.Migrations
{
[DbContext(typeof(AppDbContext))]
[Migration("20231218173546_Migrate18122035")]
partial class Migrate18122035
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.12")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("yaflay.ru.Models.Tables.Author", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int>("discordId")
.HasColumnType("integer");
b.Property<string>("discordNickName")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Author");
});
modelBuilder.Entity("yaflay.ru.Models.Tables.Blogs", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Annotation")
.IsRequired()
.HasColumnType("text");
b.Property<string>("ImageUrl")
.HasColumnType("text");
b.Property<string>("Text")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("text");
b.Property<int>("authorId")
.HasColumnType("integer");
b.Property<DateTime>("dateTime")
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.HasIndex("authorId");
b.ToTable("Blogs", "public");
});
modelBuilder.Entity("yaflay.ru.Models.Tables.Comments", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Text")
.IsRequired()
.HasColumnType("text");
b.Property<string>("creatorMail")
.IsRequired()
.HasColumnType("text");
b.Property<long>("dateTime")
.HasColumnType("bigint");
b.Property<int>("postId")
.HasColumnType("integer");
b.HasKey("Id");
b.ToTable("Comments", "public");
});
modelBuilder.Entity("yaflay.ru.Models.Tables.Redirects", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("redirectTo")
.IsRequired()
.HasColumnType("text");
b.Property<string>("uri")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Redirects");
});
modelBuilder.Entity("yaflay.ru.Models.Tables.Blogs", b =>
{
b.HasOne("yaflay.ru.Models.Tables.Author", "author")
.WithMany()
.HasForeignKey("authorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("author");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,22 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace yaflay.ru.Migrations
{
/// <inheritdoc />
public partial class Migrate18122035 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
}
}
}
+143
View File
@@ -0,0 +1,143 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using yaflay.ru.Models;
#nullable disable
namespace yaflay.ru.Migrations
{
[DbContext(typeof(AppDbContext))]
[Migration("20231219143602_Migrate191220231734")]
partial class Migrate191220231734
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.12")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("yaflay.ru.Models.Tables.Author", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<decimal>("discordId")
.HasColumnType("numeric(20,0)");
b.Property<string>("discordNickName")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Author");
});
modelBuilder.Entity("yaflay.ru.Models.Tables.Blogs", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Annotation")
.IsRequired()
.HasColumnType("text");
b.Property<string>("ImageUrl")
.HasColumnType("text");
b.Property<string>("Text")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("text");
b.Property<int>("authorId")
.HasColumnType("integer");
b.Property<DateTime>("dateTime")
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.HasIndex("authorId");
b.ToTable("Blogs", "public");
});
modelBuilder.Entity("yaflay.ru.Models.Tables.Comments", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Text")
.IsRequired()
.HasColumnType("text");
b.Property<string>("creatorMail")
.IsRequired()
.HasColumnType("text");
b.Property<long>("dateTime")
.HasColumnType("bigint");
b.Property<int>("postId")
.HasColumnType("integer");
b.HasKey("Id");
b.ToTable("Comments", "public");
});
modelBuilder.Entity("yaflay.ru.Models.Tables.Redirects", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("redirectTo")
.HasColumnType("text");
b.Property<string>("uri")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Redirects");
});
modelBuilder.Entity("yaflay.ru.Models.Tables.Blogs", b =>
{
b.HasOne("yaflay.ru.Models.Tables.Author", "author")
.WithMany()
.HasForeignKey("authorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("author");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,70 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace yaflay.ru.Migrations
{
/// <inheritdoc />
public partial class Migrate191220231734 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "uri",
table: "Redirects",
type: "text",
nullable: true,
oldClrType: typeof(string),
oldType: "text");
migrationBuilder.AlterColumn<string>(
name: "redirectTo",
table: "Redirects",
type: "text",
nullable: true,
oldClrType: typeof(string),
oldType: "text");
migrationBuilder.AlterColumn<decimal>(
name: "discordId",
table: "Author",
type: "numeric(20,0)",
nullable: false,
oldClrType: typeof(int),
oldType: "integer");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "uri",
table: "Redirects",
type: "text",
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "text",
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "redirectTo",
table: "Redirects",
type: "text",
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "text",
oldNullable: true);
migrationBuilder.AlterColumn<int>(
name: "discordId",
table: "Author",
type: "integer",
nullable: false,
oldClrType: typeof(decimal),
oldType: "numeric(20,0)");
}
}
}
+115
View File
@@ -0,0 +1,115 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using yaflay.ru.Models;
#nullable disable
namespace yaflay.ru.Migrations
{
[DbContext(typeof(AppDbContext))]
[Migration("20231223164820_Migrate321220231944")]
partial class Migrate321220231944
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.12")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("yaflay.ru.Models.Tables.Blogs", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Annotation")
.IsRequired()
.HasColumnType("text");
b.Property<string>("ImageUrl")
.HasColumnType("text");
b.Property<string>("Text")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("text");
b.Property<string>("authorId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("authorNickname")
.IsRequired()
.HasColumnType("text");
b.Property<DateTime>("dateTime")
.HasColumnType("timestamp without time zone");
b.HasKey("Id");
b.ToTable("Blogs", "public");
});
modelBuilder.Entity("yaflay.ru.Models.Tables.Comments", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Text")
.IsRequired()
.HasColumnType("text");
b.Property<string>("creatorMail")
.IsRequired()
.HasColumnType("text");
b.Property<long>("dateTime")
.HasColumnType("bigint");
b.Property<int>("postId")
.HasColumnType("integer");
b.HasKey("Id");
b.ToTable("Comments", "public");
});
modelBuilder.Entity("yaflay.ru.Models.Tables.Redirects", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("redirectTo")
.HasColumnType("text");
b.Property<string>("uri")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Redirects");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,111 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace yaflay.ru.Migrations
{
/// <inheritdoc />
public partial class Migrate321220231944 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Blogs_Author_authorId",
schema: "public",
table: "Blogs");
migrationBuilder.DropTable(
name: "Author");
migrationBuilder.DropIndex(
name: "IX_Blogs_authorId",
schema: "public",
table: "Blogs");
migrationBuilder.AlterColumn<DateTime>(
name: "dateTime",
schema: "public",
table: "Blogs",
type: "timestamp without time zone",
nullable: false,
oldClrType: typeof(DateTime),
oldType: "timestamp with time zone");
migrationBuilder.AlterColumn<string>(
name: "authorId",
schema: "public",
table: "Blogs",
type: "text",
nullable: false,
oldClrType: typeof(int),
oldType: "integer");
migrationBuilder.AddColumn<string>(
name: "authorNickname",
schema: "public",
table: "Blogs",
type: "text",
nullable: false,
defaultValue: "");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "authorNickname",
schema: "public",
table: "Blogs");
migrationBuilder.AlterColumn<DateTime>(
name: "dateTime",
schema: "public",
table: "Blogs",
type: "timestamp with time zone",
nullable: false,
oldClrType: typeof(DateTime),
oldType: "timestamp without time zone");
migrationBuilder.AlterColumn<int>(
name: "authorId",
schema: "public",
table: "Blogs",
type: "integer",
nullable: false,
oldClrType: typeof(string),
oldType: "text");
migrationBuilder.CreateTable(
name: "Author",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
discordId = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
discordNickName = table.Column<string>(type: "text", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Author", x => x.Id);
});
migrationBuilder.CreateIndex(
name: "IX_Blogs_authorId",
schema: "public",
table: "Blogs",
column: "authorId");
migrationBuilder.AddForeignKey(
name: "FK_Blogs_Author_authorId",
schema: "public",
table: "Blogs",
column: "authorId",
principalTable: "Author",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
}
}
}
+135
View File
@@ -0,0 +1,135 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using yaflay.ru.Models;
#nullable disable
namespace yaflay.ru.Migrations
{
[DbContext(typeof(AppDbContext))]
[Migration("20231225062718_Migrate25122023926")]
partial class Migrate25122023926
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.12")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("yaflay.ru.Database.Tables.ApiKey", b =>
{
b.Property<string>("Key")
.HasColumnType("text");
b.Property<decimal>("DiscordOwnerId")
.HasColumnType("numeric(20,0)");
b.Property<string>("Melon")
.IsRequired()
.HasColumnType("text");
b.Property<int>("Type")
.HasColumnType("integer");
b.HasKey("Key");
b.ToTable("ApiKeys", "public");
});
modelBuilder.Entity("yaflay.ru.Models.Tables.Blogs", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Annotation")
.IsRequired()
.HasColumnType("text");
b.Property<string>("ImageUrl")
.HasColumnType("text");
b.Property<string>("Text")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("text");
b.Property<string>("authorId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("authorNickname")
.IsRequired()
.HasColumnType("text");
b.Property<DateTime>("dateTime")
.HasColumnType("timestamp without time zone");
b.HasKey("Id");
b.ToTable("Blogs", "public");
});
modelBuilder.Entity("yaflay.ru.Models.Tables.Comments", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Text")
.IsRequired()
.HasColumnType("text");
b.Property<string>("creatorMail")
.IsRequired()
.HasColumnType("text");
b.Property<long>("dateTime")
.HasColumnType("bigint");
b.Property<int>("postId")
.HasColumnType("integer");
b.HasKey("Id");
b.ToTable("Comments", "public");
});
modelBuilder.Entity("yaflay.ru.Models.Tables.Redirects", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("redirectTo")
.HasColumnType("text");
b.Property<string>("uri")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Redirects");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,37 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace yaflay.ru.Migrations
{
/// <inheritdoc />
public partial class Migrate25122023926 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "ApiKeys",
schema: "public",
columns: table => new
{
Key = table.Column<string>(type: "text", nullable: false),
DiscordOwnerId = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
Melon = table.Column<string>(type: "text", nullable: false),
Type = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ApiKeys", x => x.Key);
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "ApiKeys",
schema: "public");
}
}
}
+132
View File
@@ -0,0 +1,132 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using yaflay.ru.Models;
#nullable disable
namespace yaflay.ru.Migrations
{
[DbContext(typeof(AppDbContext))]
partial class AppDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.12")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("yaflay.ru.Database.Tables.ApiKey", b =>
{
b.Property<string>("Key")
.HasColumnType("text");
b.Property<decimal>("DiscordOwnerId")
.HasColumnType("numeric(20,0)");
b.Property<string>("Melon")
.IsRequired()
.HasColumnType("text");
b.Property<int>("Type")
.HasColumnType("integer");
b.HasKey("Key");
b.ToTable("ApiKeys", "public");
});
modelBuilder.Entity("yaflay.ru.Models.Tables.Blogs", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Annotation")
.IsRequired()
.HasColumnType("text");
b.Property<string>("ImageUrl")
.HasColumnType("text");
b.Property<string>("Text")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("text");
b.Property<string>("authorId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("authorNickname")
.IsRequired()
.HasColumnType("text");
b.Property<DateTime>("dateTime")
.HasColumnType("timestamp without time zone");
b.HasKey("Id");
b.ToTable("Blogs", "public");
});
modelBuilder.Entity("yaflay.ru.Models.Tables.Comments", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Text")
.IsRequired()
.HasColumnType("text");
b.Property<string>("creatorMail")
.IsRequired()
.HasColumnType("text");
b.Property<long>("dateTime")
.HasColumnType("bigint");
b.Property<int>("postId")
.HasColumnType("integer");
b.HasKey("Id");
b.ToTable("Comments", "public");
});
modelBuilder.Entity("yaflay.ru.Models.Tables.Redirects", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("redirectTo")
.HasColumnType("text");
b.Property<string>("uri")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Redirects");
});
#pragma warning restore 612, 618
}
}
}
+23
View File
@@ -0,0 +1,23 @@
using Microsoft.EntityFrameworkCore;
using yaflay.ru.Database.Tables;
using yaflay.ru.Models.Tables;
namespace yaflay.ru.Models
{
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) {
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
}
public DbSet<Blogs> Blogs { get; set; }
public DbSet<Comments> Comments { get; set; }
public DbSet<Redirects> Redirects { get; set; }
public DbSet<ApiKey> ApiKeys { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
}
+22
View File
@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;
using yaflay.ru.Auth;
namespace yaflay.ru.Database.Tables;
[Table("ApiKeys", Schema = "public")]
public class ApiKey
{
[Key]
public string Key { get; set; }
[Required]
public ulong DiscordOwnerId { get; set; }
[Required]
public string Melon { get; set; }
public ApiKeyTypes Type { get; set; }
}
+26
View File
@@ -0,0 +1,26 @@
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations.Schema;
namespace yaflay.ru.Models.Tables
{
[Table("Blogs", Schema = "public")]
public class Blogs
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Title { get; set; }
public string Text { get; set; }
public string Annotation { get; set; }
public string? ImageUrl { get; set; }
public DateTime dateTime { get; set; }
public string authorId { get; set; }
public string authorNickname { get; set; }
}
public class Author
{
public int Id { get; set; }
public ulong discordId { get; set; }
public string discordNickName { get; set; }
}
}
+17
View File
@@ -0,0 +1,17 @@
using System.ComponentModel.DataAnnotations.Schema;
using System.Net.Mail;
namespace yaflay.ru.Models.Tables
{
[Table("Comments", Schema = "public")]
public class Comments
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public long dateTime { get; set; }
public string Text { get; set; }
public string creatorMail { get; set; }
public int postId { get; set; }
}
}
+12
View File
@@ -0,0 +1,12 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace yaflay.ru.Models.Tables
{
public class Redirects
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string? uri { get; set; }
public string? redirectTo { get; set; }
}
}
+75
View File
@@ -0,0 +1,75 @@
@page "{type?}"
@model yaflay.ru.Pages.AdminPanelModel
@using System.Text.Json.Nodes
@{
ViewData["Title"] = "AdminPanel";
bool isAllowed = true;
}
@if (Request.Cookies["melon"] != null)
{
if (Startup.ownerId.FirstOrDefault(Request.Cookies["cable"]).isNull())
{
<h1 align="center">Вы не авторизованы! Сасни хуйца, олух</h1>
isAllowed = false;
}
} else
{
<h1 align="center">Вы не авторизованы! Сасни хуйца, олух</h1>
isAllowed = false;
}
@if (Model.type == "article" & isAllowed){
<div class="card margin-2-vm">
<div class="card-body bg-dark">
<h5 class="card-title">Код статьи (HTML)</h5>
<div class="card-text form-group bg-dark text-muted">
<label for="titleInput">Тайтл статьи</label>
<input type="text" class="form-control bg-dark text-muted" id="titleInput" />
<label for="annotationArea">Код аннотации</label>
<textarea class="form-control bg-dark text-muted" id="annotationArea" rows="2" onkeyup="updateAnnotation(this.value)"></textarea>
<label for="textArea">Код статьи</label>
<textarea class="form-control bg-dark text-muted" id="textArea" rows="5" onkeyup="updatePreview(this.value)"></textarea>
<label for="imgInput">Ссылка на изображение</label>
<input type="url" class="form-control bg-dark text-muted" id="imgInput" ></input>
</div>
</div>
</div>
<div class="card margin-2-vm" >
<div class="card-body bg-dark">
<h5 class="card-title text-muted">Превью аннотации</h5>
<div class="card-text text-muted overflow-auto" id="annotationCard">
<code id="code"><p id="annotationText"></p></code>
</div>
<h5 class="card-title text-muted">Превью текста</h5>
<div class="card-text text-muted overflow-auto" id="previewCard">
<code id="code"><p id="blogText"></p></code>
</div>
</div>
</div>
<button type="button" id="sendBlogText" align="center" class="btn-primary margin-2-vm " onclick="sendArticleData()">Send!</button>
}
else if (Model.type == "redirects" & isAllowed)
{
<div class="card margin-2-vm">
<div class="card-body bg-dark">
<h5 class="card-title">Редиректы</h5>
<div class="card-text form-group bg-dark text-muted">
<label for="urlInput">Ссылка</label>
<input type="url" class="form-control bg-dark text-muted" id="urlInput" />
<label for="uriInput">Uri</label>
<input type="text" class="form-control bg-dark text-muted" id="uriInput" />
</div>
</div>
</div>
<button type="button" id="sendRedirect" align="center" class="btn-primary margin-2-vm " onclick="sendRedirectData()">Send!</button>
}
else if (isAllowed)
{
<h2 align="center" class="text-white absolute"><a href="/AdminPanel/redirects">Редиректы</a><a href="/AdminPanel/article"> Статьи</a></h2>
}
+14
View File
@@ -0,0 +1,14 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace yaflay.ru.Pages
{
public class AdminPanelModel : PageModel
{
public string? type = null;
public void OnGet(string? type)
{
this.type = type;
}
}
}
+93
View File
@@ -0,0 +1,93 @@
@page "{code}"
@model yaflay.ru.Pages.AuthorizeModel
@using System.Text.Json.Nodes
@using Newtonsoft.Json
@{
string path = $"{Request.Method}//{Request.Host}";
ViewData["Title"] = "Authorize";
string authorizationUrl = $"https://discord.com/api/oauth2/authorize?client_id={Startup.clientId}&response_type=code&redirect_uri={Startup.redirectUrl}&scope=identify";
<p style="display:none;">Data: @Startup.clientId @Startup.redirectUrl [@String.Join(",", Startup.ownerId)] @Model.code</p>
if (Model.code == null)
{
if (Request.Cookies["melon"]?.ToString() == null)
{
<a href="@authorizationUrl">Login while Discord</a>
}
else
{
HttpResponseMessage message;
using (var requestMessage =
new HttpRequestMessage(HttpMethod.Get, "https://discordapp.com/api/oauth2/@me"))
{
requestMessage.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", Request.Cookies["melon"]); ;
message = await Startup.client.SendAsync(requestMessage);
}
string responseBody = await message.Content.ReadAsStringAsync();
JsonNode response = JsonNode.Parse(responseBody);
if (response["user"] != null)
{
<h4>Вы авторизованы!</h4>
<a href="/AdminPanel"> Админка </a>
}
else
{
<h4>
Токен авторизации неправильный! Попробуйте <a href="@authorizationUrl">заново</a>
</h4>
}
}
}
else
{
HttpResponseMessage message;
using (var requestMessage =
new HttpRequestMessage(HttpMethod.Post, "https://discordapp.com/api/oauth2/token"))
{
requestMessage.Content = new StringContent(
@$"grant_type=authorization_code&code={Model.code}&client_id={Startup.clientId}&client_secret={Startup.clientSecret}&scope=identify&redirect_uri={Startup.redirectUrl}",
new System.Net.Http.Headers.MediaTypeHeaderValue("application/x-www-form-urlencoded")
);
message = await Startup.client.SendAsync(requestMessage);
}
string responseBody = await message.Content.ReadAsStringAsync();
JsonNode body = JsonNode.Parse(responseBody);
if (body["access_token"]?.ToString() == null)
{
<h4>Ошибка! Попробуй авторизоваться заново</h4>
Console.Error.WriteLine("debug: START \\/ \nDon't worry, this message is not bad as you think");
Console.Error.WriteLine("error: DiscordAuthorize is not worked");
Console.Error.WriteLine($"debug: Body from discord: {body}\ndebug: Sended data to discord: {message.Content.ReadAsStringAsync().Result}");
Console.Error.WriteLine($"info: Check environment data: \nClientId={Startup.clientId}\nClientSecret={Startup.clientSecret}\nRedirectUrl={Startup.redirectUrl}\nOwnerId={String.Join(",", Startup.ownerId)} ");
Console.Error.WriteLine("info: If any data is null and you set data in environment or appsettings.json, please create issue with this debug messages ");
Console.Error.WriteLine("debug: END /\\");
}
else
{
Response.Cookies.Append("melon", body["access_token"].ToString());
Response.Cookies.Append("watermelon", body["refresh_token"].ToString());
try
{
HttpContent bodytoApi;
bodytoApi = new StringContent(JsonConvert.SerializeObject(new yaflay.ru.Controllers.HomeController.authorizeBody()
{
discordId = body["user"]["id"].ToString(),
melon = body["access_token"].ToString(),
type = Auth.ApiKeyTypes.Public,
watermelon = body["watermelon"].ToString()
}));
var req = await Startup.client.PostAsync(path + "/api/authorize", bodytoApi);
}
catch(Exception ex)
{
Console.WriteLine(body);
Console.WriteLine(ex.Message);
}
Response.Redirect("/authorize");
}
}
}
+18
View File
@@ -0,0 +1,18 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace yaflay.ru.Pages
{
public class AuthorizeModel : PageModel
{
public string code;
public void OnGet(string code)
{
this.code = code;
Page();
}
}
}
+97
View File
@@ -0,0 +1,97 @@
@page "{id?}"
@model BlogModel
@using yaflay.ru.Models.Tables
@using Newtonsoft.Json
@{
string path = $"{this.Request.Scheme}://{this.Request.Host}";
if (Model.Id != 0)
{
var request = await Startup.client.GetAsync(path + "/api/Blog/" + Model.Id);
Blogs? Post = JsonConvert.DeserializeObject<Blogs>(request.Content.ReadAsStringAsync().Result);
if (Post == null)
{
ViewData["Title"] = "Blogs";
<h1 align="center">Что-то не так...</h1>
<h1 align="center">Пост не найден, но ты держи яблочко -> 🍎</h1>
} else
{
ViewData["Title"] = Post.Title;
ViewData["og:title"] = Post.Title;
ViewData["og:url"] = this.Request.Host.Host + this.Request.Path.ToString();
ViewData["og:description"] = Post.Annotation;
ViewData["og:image"] = Post.ImageUrl;
<p align="left">
<h1 align="left">@Html.Raw(Post.Title)</h1>
<h5>@Post.dateTime</h5>
</p>
<div id="blogId" style="display:none;">@Model.Id</div>
<p align="center"><img src="@Post.ImageUrl" style="width:50vmax;"/></p>
<p align="center">@Html.Raw(Post.Text)</p>
string userUrl = "https://discord.com/users/" + Post.authorId;
<h6 align="left">Статья подготовлена <a href="@userUrl">@Post.authorNickname</a></h6>
<div class="container my-5 py-5 bg-dark text-muted">
<div class="row d-flex justify-content-center">
<div class="col-md-12 col-lg-10">
<div class="card text-muted bg-dark">
<div class="card-body position-static p-4" id="allComments">
<h4 class="mb-0" id="commentBar">Последние комментарии</h4>
<h1 align="center">Дальше тьма...</h1>
</div>
</div>
</div>
</div>
</div>
}
<div class="card-footer text-white bg-dark mb-3 py-3 border-0" >
<div class="d-flex flex-start w-100">
<div class="form-outline w-100">
<label for="userEmail" class="form-label">Адрес электронной почты</label>
<input type="email" class="form-control bg-dark text-white" id="userEmail" placeholder="name@example.com" name="userEmail">
<label for="commentText" class="form-label">Комментарий</label>
<input type="text" class="form-control bg-dark text-white" id="commentText" rows="4" name="commentText">
</div>
</div>
<div class="float-end mt-2 pt-1">
<button type="button" class="btn btn-primary btn-sm" id="postComment" >Запостить коммент</button>
</div>
</div>
}
else
{
ViewData["Title"] = "Blog";
var request = await Startup.client.GetAsync(path + "/api/Blog/");
Blogs[]? allBlogs = JsonConvert.DeserializeObject<Blogs[]>(request.Content.ReadAsStringAsync().Result);
if (allBlogs.Length == 0)
{
<p>
<h1 align="center">Ничего нет...</h1>
<h1 align="center">Вот вам банан -> 🍌</h1>
</p>
}
else
{
foreach (Blogs blog in allBlogs)
{
<div class="card text-white bg-dark mb-3 text-center" style="width: 18rem;">
<img src="@blog.ImageUrl" class="card-img-top" />
<div class="card-body ">
<h5 class="card-title">@Html.Raw(blog.Title)</h5>
<p class="card-text">@Html.Raw(blog.Annotation)</p>
<a href="/Blog/@blog.Id" class="btn btn-primary center">Читать</a>
</div>
</div>
}
}
}
}
+37
View File
@@ -0,0 +1,37 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.RazorPages;
using yaflay.ru.Models.Tables;
namespace yaflay.ru.Pages
{
public class BlogModel : PageModel
{
public int Id { get; private set; }
//public Comments[] comments { get; set; }
public void OnGet(int? id)
{
Id = id ?? 0;
Page();
//comments = Startup.dbContext.Comments.Where(k => k.postId == Id).OrderBy(k => k.dateTime).Reverse().ToArray();
}
public void OnPost(int? id)
{
Id = id ?? 0;
//comments = Startup.dbContext.Comments.Where(k => k.postId == Id).OrderBy(k => k.dateTime).Reverse().ToArray();
string userEmail = Request.Form["userEmail"];
string commentMessage = Request.Form["commentText"];
if (Id == 0 || commentMessage == null || userEmail == null) { Page(); return; }
Startup.dbContext.Comments.Add(new Comments()
{
Text = commentMessage,
creatorMail = userEmail,
dateTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
postId = Id
});
Startup.dbContext.SaveChanges();
Page();
}
}
}
+6 -5
View File
@@ -1,14 +1,15 @@
@page
@page "{uri?}"
@model IndexModel
@using System.Net.Http;
@{
ViewData["Title"] = "YaFlay";
ViewData["Title"] = "yawaflua";
}
<h3 align="left" class="readme" >README.md</h3>
@{
HttpClient client = new();
string Github_readme = client.GetStringAsync("https://raw.githubusercontent.com/YaFlay/YaFlay/master/README.md").Result;
string path = $"{this.Request.Scheme}://{this.Request.Host}";
string Github_readme = Startup.client.GetStringAsync($"{path}/api/Index").Result;
<div class="text"> @Html.Raw(Github_readme) </div>
}
+30 -5
View File
@@ -1,21 +1,46 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Caching.Memory;
using yaflay.ru.Models;
using yaflay.ru.Models.Tables;
namespace yaflay.ru.Pages
{
public class IndexModel : PageModel
{
private readonly ILogger<IndexModel> _logger;
public IndexModel(ILogger<IndexModel> logger)
public IMemoryCache cache;
public AppDbContext ctx;
public string? uri { get; set; } = null;
public IndexModel(ILogger<IndexModel> logger, IMemoryCache cache, AppDbContext ctx)
{
_logger = logger;
this.cache = cache;
this.ctx = ctx;
}
public void OnGet()
public void OnGet(string? uri)
{
Page();
this.uri = uri ?? null;
Console.WriteLine(uri);
if (this.uri != null)
{
Redirects? fromCache = cache.Get<Redirects>($"redirectsWithUrl-{uri}") ?? null;
if (fromCache == null)
{
fromCache = ctx.Redirects.FirstOrDefault(k => k.uri == uri);
Console.WriteLine("Im here!");
if (fromCache != null)
cache.Set($"redirectsWithUrl-{uri}", (object)fromCache, DateTime.Now.AddMinutes(10));
}
Console.WriteLine(fromCache?.ToString());
Response.Redirect(fromCache?.redirectTo ?? "/404");
}
else
{
Page();
}
}
}
+247
View File
@@ -0,0 +1,247 @@
@page
@{
ViewData["Title"] = "500 Error";
Layout = null;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Page not found</title>
<link rel="stylesheet" href="~/css/500.css" />
</head>
<body>
<div class="main-error-page">
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="auto"
height="290"
viewBox="0 0 470 290">
<defs>
<path id="prefix__a"
d="M221.677 31.582c-55.54 19.895-112.156 36.51-167.848 55.993C33.02 94.854 8.92 106.19 5.062 129.52c-2.513 15.198 5.634 31.108 17.898 38.96 5.99 3.835 13.34 6.531 16.472 13.261 4.87 10.459-3.88 22.449-13.113 28.531-9.236 6.083-20.5 10.905-24.704 21.695-1.121 2.876-1.61 5.944-1.615 9.05v.082c.006 4.547 1.05 9.169 2.674 13.386 10.06 26.125 39.391 37.567 65.477 36.17 26.086-1.398 50.827-12.414 76.417-18.085 43.668-9.678 88.389-3.63 133.098 2.418 45.256 6.122 90.501 12.244 134.63 2.054 13.65-3.153 27.4-8.086 37.944-17.999 11.883-11.174 18.63-28.03 19.648-45.048.069-1.15.106-2.31.112-3.477v-.557c-.067-15.128-5.551-31.08-17.856-37.794-7.833-4.274-17.195-4.1-25.7-1.775-5.43 1.485-10.766 3.811-16.368 3.85-5.601.04-11.763-3-13.386-8.812-1.707-6.11 2.182-12.416 6.642-16.586 9.073-8.477 21.203-12.714 29.44-22.137 7.927-9.07 11.265-22.586 8.575-34.734-2.692-12.149-11.326-22.552-22.189-26.73-14.224-5.471-29.105-.465-44.051 4.542-14.139 4.736-28.34 9.474-42.1 5.336-2.1-.63-4.312-1.606-5.418-3.643-1.08-1.989-.835-4.511-.214-6.719 3.468-12.355 16.938-20.22 17.528-33.12.322-7.01-3.504-13.572-8.325-18.26C327.188 4.247 316.599.782 305.483.782c-28.103 0-59.605 22.132-83.806 30.8z" />
<path id="prefix__c"
d="M39.89.625c-2.162 6.638-7.77 12.79-13.571 16.612-9.236 6.082-20.5 10.904-24.704 21.694C.494 41.807.005 44.875 0 47.98v.082c.006 4.547 1.05 9.17 2.674 13.386 10.06 26.126 39.391 37.568 65.477 36.17 26.086-1.397 50.827-12.414 76.417-18.085 43.668-9.678 88.389-3.629 133.098 2.419 45.256 6.122 90.501 12.244 134.63 2.054 13.65-3.154 27.4-8.086 37.944-18 11.883-11.174 18.63-28.03 19.648-45.048.069-1.15.106-2.31.112-3.477v-.557c-.025-5.484-.761-11.079-2.277-16.3H39.89z" />
<path id="prefix__e"
d="M.99 2.778v5.157c0 1.457 1.467 2.638 3.277 2.638s3.278-1.181 3.278-2.638V2.778c0-1.457-1.467-2.637-3.278-2.637C2.457.141.99 1.321.99 2.778z" />
<path id="prefix__g"
d="M.577 2.778v5.157c0 1.457 1.468 2.638 3.279 2.638 1.81 0 3.278-1.181 3.278-2.638V2.778c0-1.457-1.468-2.637-3.278-2.637S.576 1.321.576 2.778z" />
<path id="prefix__i"
d="M.39 2.037c0 1.08.88 1.956 1.966 1.956 1.087 0 1.968-.877 1.968-1.956 0-1.08-.88-1.956-1.968-1.956C1.27.081.39.957.39 2.037z" />
<path id="prefix__k"
d="M.39 2.466c0 1.08.88 1.956 1.966 1.956 1.087 0 1.968-.875 1.968-1.956 0-1.079-.88-1.954-1.968-1.954C1.27.512.39 1.387.39 2.466z" />
<path id="prefix__m"
d="M1.963.022C.893.022.026.898.026 1.977c0 1.08.867 1.956 1.937 1.956H16.45c1.068 0 1.935-.876 1.935-1.956 0-1.079-.867-1.955-1.935-1.955H1.963z" />
<path id="prefix__o"
d="M5.214 5.34c-.85 3.38 1.072 5.145 5.14 11.15L.464 55.893l44.419 11.492 9.888-39.401c6.384-3.286 8.919-3.909 9.77-7.295.793-3.159-1.093-6.383-4.206-7.189L12.294 1.071c-.48-.125-.962-.185-1.437-.185-2.598 0-4.972 1.783-5.643 4.453z" />
<path id="prefix__q"
d="M5 6.465c-1.055 4.052 1.213 6.332 4.666 11.2l-9.2 35.38 2.075.52 9.442-36.306c-3.886-5.53-5.717-7.165-4.909-10.276.758-2.91 3.791-4.675 6.762-3.933l45.868 11.453c2.971.742 4.772 3.714 4.015 6.624-.81 3.118-3.222 3.687-9.328 6.72L44.95 64.154l2.076.518 9.2-35.38c5.404-2.654 8.514-3.59 9.57-7.646 1.047-4.032-1.447-8.15-5.563-9.177L14.365 1.016c-.635-.159-1.273-.234-1.9-.234-3.44 0-6.58 2.274-7.465 5.683z" />
<path id="prefix__s"
d="M5.916.737C2.89.737.428 3.265.428 6.37c0 3.326 2.16 4.498 7.25 9.07v32.236h43.2V15.44c5.077-4.56 7.25-5.74 7.25-9.07 0-3.105-2.462-5.633-5.488-5.633H5.916z" />
<path id="prefix__u"
d="M7.721.63C3.638.63.314 4.073.314 8.3c0 4.249 2.667 5.935 7.065 9.878v30.697h2.058V17.21C4.476 12.72 2.375 11.562 2.375 8.3c0-3.05 2.398-5.535 5.346-5.535h45.511c2.949 0 5.347 2.484 5.347 5.534 0 3.269-2.108 4.422-7.062 8.911v31.665h2.06V18.178c4.389-3.939 7.061-5.626 7.061-9.879 0-4.227-3.32-7.668-7.406-7.668H7.722z" />
<path id="prefix__w"
d="M4.278.171C2.09.171.314 1.931.314 4.097v43c0 2.168 1.776 3.926 3.964 3.926H69.79c2.187 0 3.963-1.758 3.963-3.926v-43C73.753 1.93 71.977.17 69.79.17H4.278z" />
<path id="prefix__y"
d="M.102 2.593C-.017 3.898.95 5.053 2.26 5.177c1.308.122 2.469-.835 2.591-2.138C4.97 1.735 4.007.58 2.696.456 2.62.448 2.544.445 2.47.445 1.253.445.217 1.367.102 2.593z" />
<path id="prefix__A"
d="M.007 2.613c-.119 1.303.844 2.459 2.155 2.582 1.311.122 2.472-.834 2.593-2.138.12-1.304-.843-2.46-2.154-2.582-.077-.009-.153-.011-.227-.011-1.216 0-2.253.92-2.367 2.149z" />
<path id="prefix__C"
d="M.79 3.73c-.144.275.15.627.337.37C3.783.462 7.604.373 9.772 4.237c.244.43.852-.108.639-.557C9.353 1.496 7.533.36 5.676.36 3.852.36 1.994 1.456.79 3.73z" />
<path id="prefix__E"
d="M8.699 4.235L2.878 2.667c-.528-.144-1.074.182-1.219.725-.143.547.167 1.102.693 1.243l5.821 1.572-1.076 4.048-5.821-1.572c-.528-.141-1.073.183-1.217.729-.145.544.164 1.1.692 1.24l5.822 1.573-.9 3.377 7.313 1.973c4.037 1.088 8.21-1.407 9.32-5.573.753-2.832-.102-5.71-1.996-7.605-.893-.891-2.014-1.564-3.307-1.914L9.69.511 8.7 4.235z" />
<path id="prefix__G"
d="M1.203 6.693c-1.123 4.183 1.356 8.479 5.536 9.596l7.57 2.024 1.534-5.714 2.531-9.428-7.569-2.025C10.128.966 9.445.88 8.775.88c-3.462 0-6.632 2.31-7.572 5.814z" />
</defs>
<g fill="none" fill-rule="evenodd">
<path fill="#FFF" d="M0 0H1366V800H0z" transform="translate(-448 -158)" />
<g>
<g transform="translate(-448 -158) translate(448 157) translate(0 .61)">
<mask id="prefix__b" fill="#fff">
<use xlink:href="#prefix__a" />
</mask>
<path fill="#F6F6F7"
d="M-5.995 296.763L475.995 296.763 475.995 -5.213 -5.995 -5.213z"
mask="url(#prefix__b)" />
</g>
<g transform="translate(-448 -158) translate(448 157) translate(0 193.645)">
<mask id="prefix__d" fill="#fff">
<use xlink:href="#prefix__c" />
</mask>
<path fill="#EDEDF0"
d="M-20.194 115.101L487.354 115.101 487.354 36.101 -20.194 36.101z"
mask="url(#prefix__d)" />
</g>
<path class="fio-500"
stroke="#2D3F5B"
stroke-linecap="round"
stroke-width="4"
d="M42.92 106.015c1.69-.15 3.386-.39 5.08-.454 1.496-.056 3.045.109 4.354.832 2.559 1.415 3.61 4.459 6.173 5.892 3.477 1.945 7.237 2.323 11.14 2.395 4.592.085 9.185.091 13.777.069 9.192-.045 18.386-.2 27.579.004 1.455.032 2.97.052 4.292-.562 2.606-1.208 2.6-4.556-.086-5.63-1.088-.434-2.291-.441-3.463-.441l-32.929-.022c-2.27-.001-5.629.548-5.724 3.443-.215 6.553.078 15.199.713 21.722.17 1.76.492 3.722 1.92 4.769.896.657 2.057.81 3.166.904 6.696.573 13.43-.22 20.15-.185 6.721.034 13.7.992 19.326 4.657 10.875 7.087 11.581 26.256-1.336 31.914-6.591 2.887-14.242 2.35-21.267 2.257-7.79-.103-12.714.024-20.504-.132-1.647-.034-3.648-.288-4.304-1.797-.574-1.324.355-2.913 1.64-3.573 1.285-.663 2.802-.642 4.248-.603 32.437.865 62.03 4.399 94.49 2.362 15.62-.979 26.11-9.971 29.058-25.472 2.41-12.67-.035-28.363-10.01-37.409-1.853-1.68-3.952-3.08-6.24-4.098-9.326-4.147-21.037-3.107-28.714 3.924-3.952 3.619-6.283 8.75-7.291 14.006-1.948 10.149-2.077 21.397 1.549 31.197 4.503 12.17 15.295 17.937 27.852 19.106 22.936 2.138 46.167 2.247 68.908-1.419 6.817-1.1 14.77-3.416 19.496-8.795 11.362-12.935 9.584-40.905-1.435-53.582-9.245-10.635-26.641-9.576-36.17.345-4.034 4.198-6.308 9.85-7.244 15.591-2.07 12.71-.474 27.655 8.267 37.863 5.498 6.42 14.934 9.316 22.9 11.018 5.7 1.217 11.59 1.935 17.404 1.17 5.668-.749 11.264-3.322 17.003-1.433 3.896 1.282 7.194 5.378 6.09 9.328-1.146 4.102-6.015 5.773-10.238 6.335-17.139 2.28-34.126-2.651-51.125 1.61-3.002.753-5.983 1.835-8.431 3.728-2.449 1.894-4.32 4.697-4.543 7.785-.835 11.582 23.435 6.912 30.629 10.509"
transform="translate(-448 -158) translate(448 157)" />
<g transform="translate(-448 -158) translate(448 157) translate(389.862 231.813)">
<mask id="prefix__n" fill="#fff">
<use xlink:href="#prefix__m" />
</mask>
<path class="fio"
fill="#4B4B62"
d="M-5.969 9.929L24.38 9.929 24.38 -5.973 -5.969 -5.973z"
mask="url(#prefix__n)" />
</g>
<path class="fio"
stroke="#2D3F5B"
stroke-linecap="round"
stroke-width="4"
d="M332.999 253.51c-7.766-.244-14.938 4.491-22.688 4.744-2.34.077-4.8.01-6.847-1.128-2.662-1.483-3.966-4.531-3.511-7.501.564-3.683 3.808-5.906 6.02-8.612 3.643-4.453 2.47-9.05-2.76-11.169-5.66-2.293-11.803-3.685-17.833-4.585"
transform="translate(-448 -158) translate(448 157)" />
<g class="full-torradeira">
<g transform="translate(-448 -158) translate(448 157) translate(332.51 262.987)">
<mask id="prefix__f" fill="#fff">
<use xlink:href="#prefix__e" />
</mask>
<path fill="#4B4B62"
d="M-5.006 16.566L13.541 16.566 13.541 -5.855 -5.006 -5.855z"
mask="url(#prefix__f)" />
</g>
<g transform="translate(-448 -158) translate(448 157) translate(384.066 262.987)">
<mask id="prefix__h" fill="#fff">
<use xlink:href="#prefix__g" />
</mask>
<path fill="#4B4B62"
d="M-5.418 16.566L13.129 16.566 13.129 -5.855 -5.418 -5.855z"
mask="url(#prefix__h)" />
</g>
<g transform="translate(-448 -158) translate(448 157) translate(396.056 247.4)">
<mask id="prefix__j" fill="#fff">
<use xlink:href="#prefix__i" />
</mask>
<path fill="#4B4B62"
d="M-5.605 9.989L10.318 9.989 10.318 -5.913 -5.605 -5.913z"
mask="url(#prefix__j)" />
</g>
<g transform="translate(-448 -158) translate(448 157) translate(396.056 254.793)">
<mask id="prefix__l" fill="#fff">
<use xlink:href="#prefix__k" />
</mask>
<path fill="#4B4B62"
d="M-5.605 10.418L10.318 10.418 10.318 -5.483 -5.605 -5.483z"
mask="url(#prefix__l)" />
</g>
<g class="pao-atras">
<g transform="translate(-448 -158) translate(448 157) translate(340.903 169.665)">
<mask id="prefix__p" fill="#fff">
<use xlink:href="#prefix__o" />
</mask>
<path fill="#FFDA7F"
d="M-5.53 73.379L70.718 73.379 70.718 -5.109 -5.53 -5.109z"
mask="url(#prefix__p)" />
</g>
<g transform="translate(-448 -158) translate(448 157) translate(340.903 168.466)">
<mask id="prefix__r" fill="#fff">
<use xlink:href="#prefix__q" />
</mask>
<path fill="#E6A95F"
d="M-5.53 70.667L72.03 70.667 72.03 -5.213 -5.53 -5.213z"
mask="url(#prefix__r)" />
</g>
</g>
<g class="pao-frente">
<g transform="translate(-448 -158) translate(448 157) translate(326.515 182.854)">
<mask id="prefix__t" fill="#fff">
<use xlink:href="#prefix__s" />
</mask>
<path fill="#FFDA7F"
d="M-5.568 53.67L64.123 53.67 64.123 -5.259 -5.568 -5.259z"
mask="url(#prefix__t)" />
</g>
<g transform="translate(-448 -158) translate(448 157) translate(325.316 181.655)">
<mask id="prefix__v" fill="#fff">
<use xlink:href="#prefix__u" />
</mask>
<path fill="#E6A95F"
d="M-5.68 54.87L66.634 54.87 66.634 -5.363 -5.68 -5.363z"
mask="url(#prefix__v)" />
</g>
<g transform="translate(-448 -158) translate(448 157) translate(344.301 197.242)">
<mask id="prefix__z" fill="#fff">
<use xlink:href="#prefix__y" />
</mask>
<path class="olho-esq"
fill="#633"
d="M-4.153 -6.995L12.298 -3.797 9.107 12.627 -7.346 9.429z"
mask="url(#prefix__z)" />
</g>
<g transform="translate(-448 -158) translate(448 157) translate(361.087 197.242)">
<mask id="prefix__B" fill="#fff">
<use xlink:href="#prefix__A" />
</mask>
<path class="olho-dir"
fill="#633"
d="M-4.248 -6.976L12.203 -3.778 9.011 12.645 -7.441 9.448z"
mask="url(#prefix__B)" />
</g>
<g transform="translate(-448 -158) translate(448 157) translate(350.495 206.834)">
<mask id="prefix__D" fill="#fff">
<use xlink:href="#prefix__C" />
</mask>
<path class="boca"
fill="#633"
d="M-3.14 -7.546L17.993 -3.438 14.8 12.985 -6.333 8.878z"
mask="url(#prefix__D)" />
</g>
</g>
<g class="torradeira"
transform="translate(-448 -158) translate(448 157) translate(325.316 218.624)">
<mask id="prefix__x" fill="#fff">
<use xlink:href="#prefix__w" />
</mask>
<path fill="#C81414"
d="M-5.68 57.017L79.748 57.017 79.748 -5.823 -5.68 -5.823z"
mask="url(#prefix__x)" />
</g>
</g>
<g class="raios"
stroke="#fdba55"
stroke-linecap="round"
stroke-width="1.8">
<path d="M18.393 5.769L21.35 2.82M9.304 4.452L7.306.783M14.502 3.516L14.981.207M3.272 28.271L.229 31.133M12.317 29.853L14.208 33.577M7.095 30.637L6.52 33.93"
transform="translate(-448 -158) translate(448 157) translate(260.571 203.237)" />
</g>
<g transform="translate(-448 -158) translate(448 157) translate(272.561 215.226)">
<mask id="prefix__F" fill="#fff">
<use xlink:href="#prefix__E" />
</mask>
<path class="tomada"
fill="#2D3F5B"
d="M10.383 -14.007L34.351 9.962 12.875 31.438 -11.095 7.469z"
mask="url(#prefix__F)" />
</g>
<g transform="translate(-448 -158) translate(448 157) translate(246.184 208.033)">
<mask id="prefix__H" fill="#fff">
<use xlink:href="#prefix__G" />
</mask>
<path class="tomada"
fill="#2D3F5B"
d="M10.807 -12.875L32.391 8.709 10.793 30.309 -10.793 8.724z"
mask="url(#prefix__H)" />
</g>
</g>
</g>
</svg>
<h1 class="error-title">
Woops! <br>Something went wrong :(
</h1>
<h2 class="error-subtitle">
Have you tried turning it off and on again?
</h2>
</div>
</body>
</html>
+35
View File
@@ -0,0 +1,35 @@
@page
@{
Layout = null;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Page not found</title>
<link rel="shortcut icon" type="image/png" href="#">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/404.css" />
</head>
<body>
@{
string path = $"{this.Request.Scheme}://{this.Request.Host}";
}
<div class="error">
<div class="container">
<div class="row justify-content-center">
<div class="col-lg-7 text-center">
<img src="~/img/error-404.png" alt="image 404">
<h2><b>404</b> Страница не найдена</h2>
<p>посетите главную страницу <br> возможно вы найдёте свой путь</p>
<a href="@path" class="cmn-btn mt-4">На главную</a>
</div>
</div>
</div>
</div>
</body>
</html>
+12
View File
@@ -0,0 +1,12 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace yaflay.ru.Pages
{
public class Index1Model : PageModel
{
public void OnGet()
{
}
}
}
+122 -37
View File
@@ -5,48 +5,133 @@
}
<h1>@ViewData["Title"]</h1>
<h2>End-User License Agreement (EULA) of <span class="app_name">yaflay.ru</span></h2>
Statement of Purpose
<p>This End-User License Agreement ("EULA") is a legal agreement between you and <span class="company_name">YaFlay</span>. Our EULA was created by <a href="https://www.eulatemplate.com">EULA Template</a> for <span class="app_name">yaflay.ru</span>.</p>
<p>The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").</p>
<p>This EULA agreement governs your acquisition and use of our <span class="app_name">yaflay.ru</span> software ("Software") directly from <span class="company_name">YaFlay</span> or indirectly through a <span class="company_name">YaFlay</span> authorized reseller or distributor (a "Reseller"). </p>
<p>Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works ("Commons") that the public can reliably and without fear
of later claims of infringement build upon, modify, incorporate in other
works, reuse and redistribute as freely as possible in any form whatsoever
and for any purposes, including without limitation commercial purposes.
These owners may contribute to the Commons to promote the ideal of a free
culture and the further production of creative, cultural and scientific
works, or to gain reputation or greater distribution for their Work in
part through the use and efforts of others.</p>
<p>Please read this EULA agreement carefully before completing the installation process and using the <span class="app_name">yaflay.ru</span> software. It provides a license to use the <span class="app_name">yaflay.ru</span> software and contains warranty information and liability disclaimers.</p>
<p>For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under its
terms, with knowledge of his or her Copyright and Related Rights in the
Work and the meaning and intended legal effect of CC0 on those rights.</p>
<p>If you register for a free trial of the <span class="app_name">yaflay.ru</span> software, this EULA agreement will also govern that trial. By clicking "accept" or installing and/or using the <span class="app_name">yaflay.ru</span> software, you are confirming your acceptance of the Software and agreeing to become bound by the terms of this EULA agreement.</p>
<p>If you are entering into this EULA agreement on behalf of a company or other legal entity, you represent that you have the authority to bind such entity and its affiliates to these terms and conditions. If you do not have such authority or if you do not agree with the terms and conditions of this EULA agreement, do not install or use the Software, and you must not accept this EULA agreement.</p>
<p>This EULA agreement shall apply only to the Software supplied by <span class="company_name">YaFlay</span> herewith regardless of whether other software is referred to or described herein. The terms also apply to any <span class="company_name">YaFlay</span> updates, supplements, Internet-based services, and support services for the Software, unless other terms accompany those items on delivery. If so, those terms apply.</p>
<h3>License Grant</h3>
<p><span class="company_name">YaFlay</span> hereby grants you a personal, non-transferable, non-exclusive licence to use the <span class="app_name">yaflay.ru</span> software on your devices in accordance with the terms of this EULA agreement.</p>
<p>You are permitted to load the <span class="app_name">yaflay.ru</span> software (for example a PC, laptop, mobile or tablet) under your control. You are responsible for ensuring your device meets the minimum requirements of the <span class="app_name">yaflay.ru</span> software.</p>
<p>You are not permitted to:</p>
<p> Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not
limited to, the following:</p>
<ul>i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work.</ul>
<ul>
<li>Edit, alter, modify, adapt, translate or otherwise change the whole or any part of the Software nor permit the whole or any part of the Software to be combined with or become incorporated in any other software, nor decompile, disassemble or reverse engineer the Software or attempt to do any such things</li>
<li>Reproduce, copy, distribute, resell or otherwise use the Software for any commercial purpose</li>
<li>Allow any third party to use the Software on behalf of or for the benefit of any third party</li>
<li>Use the Software in any way which breaches any applicable local, national or international law</li>
<li>use the Software for any purpose that <span class="company_name">YaFlay</span> considers is a breach of this EULA agreement</li>
ii. moral rights retained by the original author(s) and/or performer(s);
</ul>
<ul>
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
</ul>
<ul>
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
</ul>
<ul>
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
</ul>
<ul>
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation
thereof, including any amended or successor version of such
directive); and
</ul>
<ul>
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.
</ul>
<h3>Intellectual Property and Ownership</h3>
<p><span class="company_name">YaFlay</span> shall at all times retain ownership of the Software as originally downloaded by you and all subsequent downloads of the Software by you. The Software (and the copyright, and other intellectual property rights of whatever nature in the Software, including any modifications made thereto) are and shall remain the property of <span class="company_name">YaFlay</span>.</p>
<p><span class="company_name">YaFlay</span> reserves the right to grant licences to use the Software to third parties.</p>
<h3>Termination</h3>
<p>This EULA agreement is effective from the date you first use the Software and shall continue until terminated. You may terminate it at any time upon written notice to <span class="company_name">YaFlay</span>.</p>
<p>It will also terminate immediately if you fail to comply with any term of this EULA agreement. Upon such termination, the licenses granted by this EULA agreement will immediately terminate and you agree to stop all access and use of the Software. The provisions that by their nature continue and survive will survive any termination of this EULA agreement.</p>
<h3>Governing Law</h3>
<p>This EULA agreement, and any dispute arising out of or in connection with this EULA agreement, shall be governed by and construed in accordance with the laws of <span class="country">ru</span>.</p>
<p>2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer's Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
member of the public at large and to the detriment of Affirmer's heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal or
equitable action to disrupt the quiet enjoyment of the Work by the public
as contemplated by Affirmer's express Statement of Purpose.
</p>
<p>
3. Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer's express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer's Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future
time extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
"License"). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any
reason be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the remainder
of the License, and in such case Affirmer hereby affirms that he or she
will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of
action with respect to the Work, in either case contrary to Affirmer's
express Statement of Purpose.
</p>
<p>
4. Limitations and Disclaimers.
</p>
<ul>
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
</ul>
<ul>
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied,
statutory or otherwise, including without limitation warranties of
title, merchantability, fitness for a particular purpose, non
infringement, or the absence of latent or other defects, accuracy, or
the present or absence of errors, whether or not discoverable, all to
the greatest extent permissible under applicable law.
</ul>
<ul>
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without
limitation any person's Copyright and Related Rights in the Work.
Further, Affirmer disclaims responsibility for obtaining any necessary
consents, permissions or other rights required for any use of the
Work.
</ul>
<ul>
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to
this CC0 or use of the Work.
</ul>
+5 -2
View File
@@ -3,7 +3,10 @@
Layout = null;
this.Response.ContentType = "text/plain";
}
# /robots.txt file for http://www.hanselman.com/
User-agent: *
<environment include="Development,Staging">Disallow: /</environment>
<environment include="Development,Staging">Disallow: /*</environment>
<environment include="Production">Disallow: /* </environment>
<environment include="Production">Allow: /Blog </environment>
<environment include="Production">Allow: /Blog/* </environment>
<environment include="Production">Allow: /Privacy </environment>
<environment include="Production">Allow: / </environment>
+104 -11
View File
@@ -1,51 +1,144 @@
<!DOCTYPE html>
<html lang="en">
<head>
@using System.Text.Json.Nodes
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - yaflay.ru</title>
<link rel="icon" href="~/favicon.ico" />
<title>@ViewData["Title"] - @Context.Request.Host.Host</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
<!-- <link rel="stylesheet" href="~/yaflay.ru.styles.css" asp-append-version="true" /> --!/>
<link type="application/json+oembed" href="~/json/oembed.json" />
<!--<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
<!-- and it's easy to individually load additional languages -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/go.min.js"></script>
@if (!Context.Request.Path.ToString().StartsWith("/Blog/"))
{
<meta property="og:title" content="yawaflua readme" />
<meta property="og:type" content="rich" />
<meta property="og:url" content="@Context.Request.Host.Host" />
<meta property="og:image" content="https://user-images.githubusercontent.com/5713670/87202985-820dcb80-c2b6-11ea-9f56-7ec461c497c3.gif" />
<meta property="og:description"
content="Here you can check info about yawaflua: social networks, programming languages that he knows and his projects." />
<meta property="og:locale" content="en_US" />
<meta property="og:site_name" content="yawaflua.ru" />
<link type="application/json+oembed" href="~/json/oembed.json" />
}
else if (Context.Request.Path.ToString().StartsWith("/Blog/"))
{
<meta property="og:title" content="@ViewData["og:title"]" />
<meta property="og:type" content="rich" />
<meta property="og:url" content="@ViewData["og:url"]" />
<meta property="og:image" content="@ViewData["og:image"]" />
<meta property="og:description"
content="@ViewData["og:description"]" />
<meta property="og:locale" content="ru_RU" />
<meta property="og:site_name" content="yawaflua.ru" />
}
</head>
<body>
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light border-bottom box-shadow mb-3" style="background-color: #2c2c2c;">
<div class="container">
<a class="navbar-brand" asp-area="" asp-page="/Index">yaflay.ru</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
<ul class="navbar-nav flex-grow-1">
<a class="nav-link " style="color: cornflowerblue;" asp-area="" asp-page="/Index">
@Context.Request.Host.Host
</a>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
<a class="nav-link text-white" asp-area="" asp-page="/Index">Home</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
<a class="nav-link text-white" asp-area="" asp-page="/Privacy">Privacy</a>
</li>
<li class="nav-item">
<a class="nav-link text-white" asp-area="" asp-page="/Blog">Blog</a>
</li>
@{
Context.Response.Cookies.Delete("cable");
if (Context.Request.Cookies["melon"] != null)
{
HttpResponseMessage message;
using (var requestMessage =
new HttpRequestMessage(HttpMethod.Get, "https://discordapp.com/api/oauth2/@me"))
{
requestMessage.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", Context.Request.Cookies["melon"]); ;
message = await Startup.client.SendAsync(requestMessage);
}
string responseBody = await message.Content.ReadAsStringAsync();
JsonNode response = JsonNode.Parse(responseBody);
if (!response["user"].isNull())
{
Context.Response.Cookies.Append("cable", response["user"]["id"].ToString());
string userName = response["user"]["global_name"].ToString();
<li class="nav-item">
<a href="/logout"
class="nav-link blurple hover:decoration-wavy underline dashed decoration-purple"
style="color: #5865F2; font-size: calc(var(--bs-body-font-size) + .15rem);">
@userName
</a>
</li>
}
}
}
</ul>
</div>
</div>
</nav>
</header>
<div class="migratePushUp">
@{
if (!Context.Request.Host.Host.StartsWith("yawaflua.ru"))
{
<div aria-live="polite" aria-atomic="true" style="margin-right: 3vh;">
<div class="toast bg-dark right-1vm absolute fixed" style="bottom: 0; display:block;">
<div class="toast-header bg-dark" >
<strong class="mr-auto left-1vm absolute">@Context.Request.Host.Host</strong>
<small class="absolute right-1vm">Now</small>
</div>
<div class="toast-body text-muted">
This site is outdated. Use <a href="https://yawaflua.ru">new site</a>
</div>
</div>
</div>
}
}
</div>
<div class="container">
<main role="main" class="pb-3">
@RenderBody()
</main>
</div>
<footer class="border-top footer text-muted">
<div class="container">
&copy; 2023 - yaflay.ru - <a asp-area="" asp-page="/Privacy">Privacy</a>
<footer class="border-top footer text-muted margin-2-vm">
<div class="container margin-2-vm">
&copy; 2023 - @Context.Request.Host.Host - <a asp-area="" asp-page="/Privacy">Privacy</a>
<b class="flex-row margin-2-vm container-md">
сrafted by <a href="https://yawaflua.ru/gh" class="underline dashed decoration-purple text-white hover:decoration-wavy">yawaflua</a>
</b>
</div>
</footer>
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
<script src="~/js/site.js"></script>
@if (Context.Request.Path.ToString().StartsWith("/AdminPanel"))
{
<script src="~/js/AdminPanel.js"></script>
}
@await RenderSectionAsync("Scripts", required: false)
</body>
+30 -4
View File
@@ -1,18 +1,44 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using yaflay.ru;
public class Program
{
public static void Main() => CreateHostBuilder()
.Build()
.Run();
public static void Main()
{
Func<string, string?> parse = (string name) => Environment.GetEnvironmentVariable(name) ?? null;
Startup.clientId = parse("CLIENTID");
Startup.clientSecret = parse("CLIENTSECRET");
Startup.redirectUrl = parse("REDIRECTURL");
if (!(parse("PSQL_HOST") == null | parse("PSQL_USER") == null | parse("PSQL_PASSWORD") == null | parse("PSQL_DATABASE") == null))
{
Startup.connectionString = $"Host={parse("PSQL_HOST")};Username={parse("PSQL_USER")};Password={parse("PSQL_PASSWORD")};Database={parse("PSQL_DATABASE")}";
}
if (parse("OWNERID") != null)
{
Startup.ownerId = new string?[] { parse("OWNERID") };
}
Startup.readmeFile = parse("READMEFILE");
CreateHostBuilder()
.Build()
.Run();
}
private static IHostBuilder CreateHostBuilder()
{
return Host.CreateDefaultBuilder()
.ConfigureWebHostDefaults(webHost => {
webHost.UseStartup<Startup>();
webHost.UseStaticWebAssets();
webHost.UseKestrel(kestrelOptions => { kestrelOptions.ListenAnyIP(80); });
webHost.UseKestrel(kestrelOptions => { kestrelOptions.ListenAnyIP(80);});
});
}
}
public static class StaticProgram
{
public static bool isNull(this object? value)
{
return value == null;
}
}
+77 -2
View File
@@ -1,4 +1,79 @@
# Hello, there!
This is my custom redirector, used in my profile, with url: [yaflay.ru](https://yaflay.ru/)
[![](https://img.shields.io/website?url=https%3A%2F%2Fyawaflua.ru)](https://yawaflua.ru)
[![Publish Docker image](https://github.com/yawaflua/yaflay.ru/actions/workflows/docker-image.yml/badge.svg)](https://github.com/yawaflua/yaflay.ru/actions/workflows/docker-image.yml)
![](https://img.shields.io/github/license/yawaflua/yaflay.ru)
![Docker release](https://img.shields.io/docker/v/yaflay/yaflay.ru/latest?style=for-the-badge&logo=docker&color=%235865F2)
This is my custom site, with url: [yawaflua.ru](https://yawaflua.ru/)
Used frameworks: Asp.Net, Razor, jQuery
Thanks for the help to [@Mih4n](https://github.com/Mih4n)!
If you wanna help me, create Issue or Pull request.
# Features
- Authorization with discord OAuth2
- Main page is downloaded from user`s github readme(like [this](https://github.com/yawaflua/yawaflua))
- Blog system with loading comments after render a page, for optimization
- Admin panel for blog`s, can make article for blog and write to db new redirect setting(Discord OAuth2)
- Set discord oauth2 and database settings from .env(docker-compose file, another docker-type function) or appsettings.json(only one from this)
# How to start?
You should to use this command for download this package from ghcr:
### For latest version
```cli
docker pull ghcr.io/yawaflua/yaflay.ru:master
```
### For stable version
```cli
docker pull ghcr.io/yawaflua/yaflay.ru:latest
```
After that create docker-compose file, for example:
```yml
version: "3.9"
services:
site:
image: ghcr.io/yawaflua/yaflay.ru:master
environment:
PSQL_HOST: example.com
PSQL_USER: root
PSQL_DATABASE: MySite
PSQL_PASSWORD: root
REDIRECTURL: https://example.com/authorize
CLIENTSECRET: aAbBcCdD123123
CLIENTID: 1111111111111111111
// You can add many ids, used "," like this:
// OWNERID: 111111111111111, 111111111111111, 1111111111111
OWNERID: 1111111111111111
READMEFILE: https://raw.githubusercontent.com/example/example/main/README.md
```
For normal work this site need to give psql data to docker environ, or appsettings.json, if you download this project from github manually
Example data for appsettings.json:
```json
{
"DetailedErrors": true,
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"clientId": "111111111111",
"clientSecret": "aAbBcCdD",
"redirectUrl": "https://example.com/authorize",
"connectionString": "Host=example.com;Username=root;Password=root;Database=MySite;",
"__comment": {
"__comment": "You can add many ids, used \",\" like this:",
"ownerId": "111111111111111, 1111111111, 11111111111, 1111111111111",
"__comment_2": "please, didnt use dictionary-typed json value"
},
"ownerId": "1111111111",
"readmeFile": "https://raw.githubusercontent.com/example/example/main/README.md"
}
```
# Support me
[boosty](https://yawaflua.ru/boosty) - boosty
[patreon](https://yawaflua.ru/patreon) - patreon
+109 -12
View File
@@ -1,51 +1,148 @@
using System;
using System.Net;
using System.Reflection.Metadata.Ecma335;
using System.Runtime.CompilerServices;
using DotNetEd.CoreAdmin;
using Microsoft.AspNetCore.Authentication;
using Microsoft.EntityFrameworkCore;
using yaflay.ru.Auth;
using yaflay.ru.Models;
namespace yaflay.ru
{
public class Startup
{
private readonly IConfiguration configuration;
public static CookieContainer cookieContainer = new();
public static HttpClientHandler handler = new() { CookieContainer = cookieContainer};
public static HttpClient client = new(handler);
public static AppDbContext? dbContext;
public static string? clientId { get; set; } = null;
public static string? clientSecret { get; set; } = null;
public static string? redirectUrl { get; set; } = null;
public static string[]? ownerId { get; set; } = null;
public static string? readmeFile { get; set; } = null;
public static string? connectionString { private get; set; } = null;
public Startup()
{
configuration = new ConfigurationBuilder()
.AddEnvironmentVariables(prefix: "m.")
.AddJsonFile("appsettings.json", optional: true)
.Build();
if (clientId == null | clientSecret == null | redirectUrl == null)
{
clientId = configuration.GetValue<string>("clientId");
clientSecret = configuration.GetValue<string>("clientSecret");
redirectUrl = configuration.GetValue<string>("redirectUrl");
}
if (connectionString == null)
{
connectionString = configuration.GetValue<string>("connectionString");
Console.WriteLine("Connectionstring" + connectionString);
if (connectionString == null)
{
throw new ArgumentException("ConnectionString is null!");
}
}
if (ownerId == null)
{
ownerId = new[] { configuration.GetValue<string>("ownerId") };
if (ownerId?.Length == 0)
{
throw new ArgumentException("Owner id is null!");
}
}
if (readmeFile == null)
{
readmeFile = configuration.GetValue<string>("readmeFile");
if (readmeFile == null)
{
throw new ArgumentException("ReadmeFile link is null");
}
}
}
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddRouting();
services.AddRazorPages();
services.AddMvc()
services.AddControllers()
.AddRazorPagesOptions(options =>
{
options.Conventions.AddPageRoute("/robots.txt", "/RobotsTxt");
options.Conventions.AddPageRoute("/RobotsTxt", "/Robots.txt");
options.Conventions.AddPageRoute("/RobotsTxt", "/robots.txt");
options.Conventions.AddPageRoute("/NotFound", "/404");
options.Conventions.AddPageRoute("/IternalErrorPage", "/500");
options.Conventions.AddPageRoute("/Authorize", "/authorize");
});
//services.AddDirectoryBrowser();
services
.AddCors(k => { k.AddDefaultPolicy(l => { l.AllowAnyHeader(); l.AllowAnyMethod(); l.AllowAnyOrigin(); }); })
.AddRouting()
.AddTransient<ApiKeyAuthantication>()
.AddSingleton(configuration)
.AddDbContext<AppDbContext>(c => c.UseNpgsql(connectionString: connectionString))
.AddAuthorization(k =>
{
k.AddPolicy("DISCORD-OAUTH-PUBLIC", policyBuilder => {
policyBuilder.RequireAuthenticatedUser();
policyBuilder.RequireClaim("Bearer", "Public");
});
k.AddPolicy("DISCORD-OAUTH-PRIVATE", policyBuilder => {
policyBuilder.RequireAuthenticatedUser();
policyBuilder.RequireClaim("Bearer", "Private");
});
})
.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = "Bearer";
options.DefaultChallengeScheme = "Bearer";
options.AddScheme<ApiKeyAuthantication>("DISCORD-OAUTH-PRIVATE", "DISCORD-OAUTH-PRIVATE");
options.AddScheme<ApiKeyAuthantication>("DISCORD-OAUTH-PUBLIC", "DISCORD-OAUTH-PUBLIC");
}).AddScheme<AuthenticationSchemeOptions, ApiKeyAuthantication>("Bearer", options => {});
services.AddMvc()
.AddRazorPagesOptions(options =>
{
options.Conventions.AddPageRoute("/RobotsTxt", "/Robots.txt");
options.Conventions.AddPageRoute("/RobotsTxt", "/robots.txt");
options.Conventions.AddPageRoute("/NotFound", "/404");
options.Conventions.AddPageRoute("/IternalErrorPage", "/500");
options.Conventions.AddPageRoute("/Authorize", "/authorize");
});
services.AddRazorPages();
dbContext = services.BuildServiceProvider().GetRequiredService<AppDbContext>();
#if DEBUG == true
services.AddCoreAdmin("admin");
#endif
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// Add services to the container.
// app.Services.AddRazorPages();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseHsts();
}
// Configure the HTTP request pipeline.
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
#if DEBUG
app.UseCoreAdminCustomTitle("yawaflua");
app.UseCoreAdminCustomAuth((k) => Task.FromResult(true));
app.UseCoreAdminCustomUrl("admin/coreadmin");
#endif
app.UseCors(k => { k.AllowAnyMethod(); k.AllowAnyOrigin(); k.AllowAnyHeader(); });
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
endpoints.MapRazorPages();
endpoints.MapControllers();
});
}
+4 -1
View File
@@ -5,5 +5,8 @@
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
},
"clientId": "111111111111",
"clientSecret": "aAbBcCdD",
"redirectUrl": "https://example.com/authorize"
}
-9
View File
@@ -1,9 +0,0 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
+3 -3
View File
@@ -1,6 +1,6 @@
{
"github": "https://github.com/YaFlay",
"gh": "https://github.com/YaFlay",
"github": "https://github.com/yawaflua",
"gh": "https://github.com/yawaflua",
"bump": "https://discord.gg/bump-1119294432949325955",
"shitpost": "https://t.me/yaflay_shitposts",
"boosty": "https://boosty.to/yaflay",
@@ -8,5 +8,5 @@
"gh-team": "https://github.com/PoopStore-Team",
"twitch": "https://twitch.tv/bebra_yaflay",
"patreon": "https://patreon.com/yaflay",
"steam": "https://steamcommunity.com/id/bebra_YaFlay/"
"steam": "https://steamcommunity.com/id/yawaflua/"
}
+162
View File
@@ -0,0 +1,162 @@
@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600;700&family=Roboto&family=Playfair+Display&display=swap");
html {
scroll-behavior: smooth;
}
body {
font-family: "Roboto", sans-serif;
color: #6f6f6f;
font-size: 16px;
padding: 0;
margin: 0;
font-weight: 400;
position: relative;
line-height: 1.7;
background-color: #f8f6ff;
}
img {
max-width: 100%;
height: auto;
}
h1 {
font-size: 62px;
}
h2 {
font-size: 32px;
}
@media (max-width: 991px) {
h2 {
font-size: 36px;
}
}
@media (max-width: 575px) {
h2 {
font-size: 28px;
}
}
h3 {
font-size: 24px;
}
h4 {
font-size: 22px;
}
@media (max-width: 767px) {
h4 {
font-size: 20px;
}
}
h5 {
font-size: 20px;
}
@media (max-width: 767px) {
h5 {
font-size: 18px;
}
}
h6 {
font-size: 18px;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: "Poppins", sans-serif;
color: #525252;
font-weight: 600;
margin: 0;
line-height: 1.4;
}
h1 > a,
h2 > a,
h3 > a,
h4 > a,
h5 > a,
h6 > a {
font-family: "Poppins", sans-serif;
color: #525252;
font-weight: 600;
-webkit-transition: all 0.3s;
-o-transition: all 0.3s;
transition: all 0.3s;
line-height: 1.4;
}
p,
li,
span {
margin: 0;
}
a {
text-decoration: none;
display: inline-block;
font-family: "Roboto", sans-serif;
font-weight: 400;
}
a:hover {
text-decoration: none;
}
.cmn-btn {
padding: 12px 35px;
text-transform: uppercase;
border-radius: 5px;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
-ms-border-radius: 5px;
-o-border-radius: 5px;
background-color: #6e41ff;
box-shadow: 0px 10px 20px 0px rgba(0, 0, 0, 0.15);
-webkit-transition: all 0.3s;
-o-transition: all 0.3s;
transition: all 0.3s;
color: #ffffff;
}
.cmn-btn:hover {
color: #ffffff;
background-color: #5b28ff;
}
.error {
position: relative;
padding: 120px 0;
}
.error .title {
font-size: 42px;
margin-top: 30px;
margin-bottom: 15px;
}
@media (max-width: 480px) {
.error .title {
font-size: 32px;
}
}
.error .title b {
font-size: 72px;
color: #f45570;
}
.error p {
font-size: 18px;
}
+469
View File
@@ -0,0 +1,469 @@
@import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap');
.main-error-page {
min-height: 600px;
margin: 0px auto;
width: auto;
max-width: 560px;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
.error-title {
max-width: 529px;
font-family: Roboto;
font-size: 38px;
font-weight: bold;
font-stretch: normal;
font-style: normal;
line-height: normal;
letter-spacing: normal;
text-align: center;
color: #4b4b62;
margin-bottom: 16px;
}
.error-subtitle {
max-width: 568px;
font-family: Roboto;
font-size: 16px;
font-weight: normal;
font-stretch: normal;
font-style: normal;
line-height: 1.31;
letter-spacing: normal;
text-align: center;
color: #4b4b62;
margin-bottom: 24px;
}
svg {
margin-bottom: 16px;
}
.full-torradeira {
}
.torradeira {
}
.pao-atras {
animation: leftright 1s alternate infinite;
transform-origin: center;
}
.pao-frente {
animation: leftright 1s 0.3s alternate infinite;
transform-origin: center;
}
.olho-esq {
animation: sad 2s alternate infinite;
transform-origin: center;
}
.olho-dir {
animation: sad 2s alternate infinite;
transform-origin: center;
}
.boca {
animation: sad 2s alternate infinite;
transform-origin: center;
}
.raios {
-webkit-animation: flicker-4 4s linear infinite both;
animation: flicker-4 4s linear infinite both;
}
.tomada {
-webkit-animation: vibrate-1 3s linear infinite both;
animation: vibrate-1 3s linear infinite both;
}
.fio-500 {
-webkit-animation: vibrate-1 3s linear infinite both;
animation: vibrate-1 3s linear infinite both;
}
.fio {
-webkit-animation: vibrate-1 3s linear infinite both;
animation: vibrate-1 3s linear infinite both;
}
@keyframes scales {
from {
transform: scale(0.98);
}
to {
transform: scale(1);
}
}
/* ----------------------------------------------
* Generated by Animista on 2020-4-1 14:58:16
* Licensed under FreeBSD License.
* See http://animista.net/license for more info.
* w: http://animista.net, t: @cssanimista
* ---------------------------------------------- */
/**
* ----------------------------------------
* animation flicker-4
* ----------------------------------------
*/
@-webkit-keyframes flicker-4 {
0%, 100% {
opacity: 1;
}
31.98% {
opacity: 1;
}
32% {
opacity: 0;
}
32.8% {
opacity: 0;
}
32.82% {
opacity: 1;
}
34.98% {
opacity: 1;
}
35% {
opacity: 0;
}
35.7% {
opacity: 0;
}
35.72% {
opacity: 1;
}
36.98% {
opacity: 1;
}
37% {
opacity: 0;
}
37.6% {
opacity: 0;
}
37.62% {
opacity: 1;
}
67.98% {
opacity: 1;
}
68% {
opacity: 0;
}
68.4% {
opacity: 0;
}
68.42% {
opacity: 1;
}
95.98% {
opacity: 1;
}
96% {
opacity: 0;
}
96.7% {
opacity: 0;
}
96.72% {
opacity: 1;
}
98.98% {
opacity: 1;
}
99% {
opacity: 0;
}
99.6% {
opacity: 0;
}
99.62% {
opacity: 1;
}
}
@keyframes flicker-4 {
0%, 100% {
opacity: 1;
}
31.98% {
opacity: 1;
}
32% {
opacity: 0;
}
32.8% {
opacity: 0;
}
32.82% {
opacity: 1;
}
34.98% {
opacity: 1;
}
35% {
opacity: 0;
}
35.7% {
opacity: 0;
}
35.72% {
opacity: 1;
}
36.98% {
opacity: 1;
}
37% {
opacity: 0;
}
37.6% {
opacity: 0;
}
37.62% {
opacity: 1;
}
67.98% {
opacity: 1;
}
68% {
opacity: 0;
}
68.4% {
opacity: 0;
}
68.42% {
opacity: 1;
}
95.98% {
opacity: 1;
}
96% {
opacity: 0;
}
96.7% {
opacity: 0;
}
96.72% {
opacity: 1;
}
98.98% {
opacity: 1;
}
99% {
opacity: 0;
}
99.6% {
opacity: 0;
}
99.62% {
opacity: 1;
}
}
/* ----------------------------------------------
* Generated by Animista on 2020-4-1 15:17:57
* Licensed under FreeBSD License.
* See http://animista.net/license for more info.
* w: http://animista.net, t: @cssanimista
* ---------------------------------------------- */
/**
* ----------------------------------------
* animation vibrate-1
* ----------------------------------------
*/
@-webkit-keyframes vibrate-1 {
0% {
-webkit-transform: translate(0);
transform: translate(0);
}
20% {
-webkit-transform: translate(-2px, 2px);
transform: translate(-2px, 2px);
}
40% {
-webkit-transform: translate(-2px, -2px);
transform: translate(-2px, -2px);
}
60% {
-webkit-transform: translate(2px, 2px);
transform: translate(2px, 2px);
}
80% {
-webkit-transform: translate(2px, -2px);
transform: translate(2px, -2px);
}
100% {
-webkit-transform: translate(0);
transform: translate(0);
}
}
@keyframes vibrate-1 {
0% {
-webkit-transform: translate(0);
transform: translate(0);
}
20% {
-webkit-transform: translate(-2px, 2px);
transform: translate(-2px, 2px);
}
40% {
-webkit-transform: translate(-2px, -2px);
transform: translate(-2px, -2px);
}
60% {
-webkit-transform: translate(2px, 2px);
transform: translate(2px, 2px);
}
80% {
-webkit-transform: translate(2px, -2px);
transform: translate(2px, -2px);
}
100% {
-webkit-transform: translate(0);
transform: translate(0);
}
}
/* ----------------------------------------------
* Generated by Animista on 2020-4-1 15:42:45
* Licensed under FreeBSD License.
* See http://animista.net/license for more info.
* w: http://animista.net, t: @cssanimista
* ---------------------------------------------- */
/**
* ----------------------------------------
* animation wobble-ver-right
* ----------------------------------------
*/
@-webkit-keyframes wobble-ver-right {
0%, 100% {
-webkit-transform: translateY(0) rotate(0);
transform: translateY(0) rotate(0);
-webkit-transform-origin: 50% 50%;
transform-origin: 50% 50%;
}
15% {
-webkit-transform: translateY(-30px) rotate(6deg);
transform: translateY(-30px) rotate(6deg);
}
30% {
-webkit-transform: translateY(15px) rotate(-6deg);
transform: translateY(15px) rotate(-6deg);
}
45% {
-webkit-transform: translateY(-15px) rotate(3.6deg);
transform: translateY(-15px) rotate(3.6deg);
}
60% {
-webkit-transform: translateY(9px) rotate(-2.4deg);
transform: translateY(9px) rotate(-2.4deg);
}
75% {
-webkit-transform: translateY(-6px) rotate(1.2deg);
transform: translateY(-6px) rotate(1.2deg);
}
}
@keyframes sad {
0% {
transform: rotateX(0deg) rotateY(0deg);
}
100% {
transform: rotateX(10deg) rotateY(5deg);
}
}
@keyframes leftright {
0% {
transform: rotateZ( 0deg)
}
100% {
transform: rotateZ( -15deg)
}
}
+50 -2
View File
@@ -6,9 +6,16 @@ html {
color: white;
}
.app_name {
font-size: calc(12px + 1vmax);
}
.readme{
font-family: 'Anonymous Pro';
}
.stats {
width: 60vmax;
max-width: 1000px;
}
body {
background: #2c2c2c;
color: white;
@@ -29,7 +36,18 @@ nav {
font-size: 16px;
}
}
.absolute {
position: absolute;
}
.fixed {
position:fixed;
}
.right-1vm {
right: 1vmax;
}
.left-1vm {
left: 1vmax;
}
html {
position: relative;
min-height: 100%;
@@ -43,6 +61,21 @@ div .text {
border: solid white;
border-width: 4px;
}
.margin-2-vm {
margin: 2vmax;
}
.underline{
text-decoration-line: underline;
}
.hover\:decoration-wavy:hover {
text-decoration-style: wavy
}
.dashed {
text-decoration-style: dashed;
}
.decoration-purple{
text-decoration-color: purple;
}
p {
margin-right: 5vh;
margin-left: 5vh;
@@ -53,7 +86,22 @@ img {
margin-bottom: 1vh;
}
.bot-1 {
padding-bottom: 1vmax;
}
body {
margin-bottom: 60px;
}
.margin-left-2-vm{
margin-left: 2vmax;
}
.margin-right-2-vm {
margin-right: 2vmax;
}
.width-4 {
width: 4vmax;
}
.blurple {
color: #5865F2;
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 647 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

+55
View File
@@ -0,0 +1,55 @@
function updatePreview(value) {
var blogText = $("#previewCard").children("#code").children("#blogText");
blogText.empty();
blogText.append(value);
}
function updateAnnotation(value) {
var blogText = $("#annotationCard").children("#code").children("#annotationText");
blogText.empty();
blogText.append(value);
}
function sendArticleData() {
let melon = document.cookie.split(';')[0].replace("melon=", "");
let body = `{
"title": "${$("#titleInput").val().replace(/"/g, '\"')}",
"annotation": "${$("#annotationArea").val().replace(/\n/g, " \\n").replace(/"/g, '\"')}}",
"text": "${$("#textArea").val().replace(/\n/g, " \\n").replace(/"/g, '\"')}",
"image": "${$("#imgInput").val()}",
"author": "${melon}"
}`;
fetch("/api/Blog", {
method: "POST",
headers: {
Authorization: `Bearer ${melon}`,
"Content-Type": "application/json"
},
body: body
}).then(k => console.log(k));
$("#titleInput").val('');
$("#annotationArea").val('');
$("#textArea").val('');
$("#imgInput").val('');
}
function sendRedirectData() {
console.log("click!")
let melon = document.cookie.split(';')[0].replace("melon=", "");
let body = `{
"url": "${$("#urlInput").val()}",
"uri": "${$("#uriInput").val()}",
"author": "${melon}"
}`;
fetch("/api/redirects", {
method: "POST",
headers: {
Authorization: `Bearer ${melon}`,
"Content-Type": "application/json"
},
body: body
}).then(k => console.log(k));
$("#urlInput").val('');
$("#uriInput").val('');
}
+43 -3
View File
@@ -1,4 +1,44 @@
// Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification
// for details on configuring this project to bundle and minify static web assets.
let blogId = $("#blogId").text();
function loadComments() {
if (document.location.pathname.startsWith("/Blog")) {
fetch(`/api/Blog/${blogId}/comments`)
.then(response => {
let data = response.json();
data.then(k => {
for (let i = 0; i < k.length; i++) {
let date = new Date(k[i].dateTime * 1000);
$("#commentBar").after(
`<div class="d-flex flex flex-start bg-dark bot-1">
<div class="container">
<h6 class="fw-bold mb-1">${k[i].creatorMail}</h6>
<div class="d-flex align-items-center mb-3">
<p class="mb-0">
${date.toLocaleString()}
</p>
</div>
<p class="mb-0">
${k[i].text}
</p>
</div>
</div>`
)
}
});
});
}
}
$("#postComment").click(
function () {
var contentBody = {
text: $("#commentText").val(),
sender: $("#userEmail").val()
}
$.ajax(`/api/Blog/${blogId}/comments`, {
data: JSON.stringify(contentBody),
contentType: "application/json",
method: "post"
}).done(response => { $("#commentText").val(''); $("#userEmail").val(''); $("#commentBar").empty(); loadComments(); })
// Write your JavaScript code.
}
);
$(loadComments());
+6 -6
View File
@@ -1,13 +1,13 @@
{
"embeds": [
{
"type": "link",
"url": "https://yaflay.ru/",
"title": "YaFlay ReadMe",
"description": "Here you can learn about YaFlay: social networks, programming languages that he knows and his projects.",
"type": "rich",
"url": "https://yawaflua.ru/",
"title": "ReadAbout yawaflua",
"description": "Here you can get info about yawaflua: social networks, programming languages that he knows and his projects.",
"thumbnail": {
"url": "https://avatars.githubusercontent.com/u/93622229?v=4",
"proxy_url": "https://avatars.githubusercontent.com/u/93622229?v=4",
"url": "https://user-images.githubusercontent.com/5713670/87202985-820dcb80-c2b6-11ea-9f56-7ec461c497c3.gif",
"proxy_url": "https://user-images.githubusercontent.com/5713670/87202985-820dcb80-c2b6-11ea-9f56-7ec461c497c3.gif",
"width": 1200,
"height": 1200
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

+15 -1
View File
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UserSecretsId>0c1057bc-b206-4a40-b003-9b6299aa9c64</UserSecretsId>
@@ -11,7 +11,21 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AspNet.Security.OAuth.Discord" Version="7.0.4" />
<PackageReference Include="CoreAdmin" Version="2.7.1" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.18.1" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.12" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.12" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.12">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.11" />
</ItemGroup>
<ItemGroup>
<Folder Include="Migrations\" />
</ItemGroup>
</Project>
+5
View File
@@ -5,6 +5,11 @@ VisualStudioVersion = 17.6.33723.286
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "yaflay.ru", "yaflay.ru.csproj", "{3AA2FE9B-D1AF-4B12-B090-7E4529BA40E0}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{82D95147-E21B-45B6-B636-A145A498D56E}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU