Fix bug, remove literals (#629)
* Use ModeratorDir variable * Rename cookieHelper to cookie_helper for consistency * Use named constant instead of literals * Fix ability to upload when uploads are disabled The old code let people upload under the right conditions when uploads were disabled. (ie: User is banned and config.AdminAreStillAllowedTo is false) * Increase timeout (fixes #517) * Fix inconsistent indentation *.{js, css} (fix #583) * Fix negative page Temporary fix. The issue was that going to a negative page caused the sql query to have a negative offset. This caused an error in the database query. We need to cleanup this code, but this will work for now. * Fix wrong PG_DATA directory due to upgrade to 9.6 * Add server status link to FAQ * Fix failing tests * Clarify group_vars/all and hosts doc * Add a wrapper to protect /mod route * Fix login page not showing form errors
Cette révision appartient à :
Parent
9ca99aae8a
révision
7eee47b0d3
|
@ -91,5 +91,9 @@ Access the website by going to [localhost:9999](http://localhost:9999).
|
|||
# LICENSE
|
||||
This project is licensed under the MIT License - see the LICENSE.md file for details
|
||||
|
||||
# Contributing
|
||||
|
||||
Use tabs for css and js files.
|
||||
|
||||
# Disclaimer
|
||||
We take no legal responsibility for anything this code is used for. This is purely an educational proof of concept.
|
||||
|
|
|
@ -13,7 +13,7 @@ const (
|
|||
// LastOldTorrentID is the highest torrent ID
|
||||
// that was copied from the original Nyaa
|
||||
LastOldTorrentID = 923000
|
||||
TableName = "torrents"
|
||||
TorrentsTableName = "torrents"
|
||||
CommentsTableName = "comments"
|
||||
// for sukebei
|
||||
//TableName = "sukebei_torrents"
|
||||
|
|
|
@ -69,8 +69,13 @@ volumes.
|
|||
> caching will be done. Ansible assume you have a user on the remote that has
|
||||
> sudo (no password).
|
||||
|
||||
You'll have to change a few variables in [hosts](host) and maybe tweak a few in
|
||||
[group_vars/all](group_vars/all).
|
||||
You'll have to change a few variables in [hosts](host). Replace the host:ip
|
||||
address to the host:ip of the target server. You can also change the user
|
||||
ansible uses to connect to the server. The user needs to have sudo ALL.
|
||||
|
||||
You'll also maybe have to tweak a few variables in
|
||||
[group_vars/all](group_vars/all) such as the database password, etc (but should
|
||||
probably be left like this).
|
||||
|
||||
|
||||
### Setup server playbook
|
||||
|
@ -149,5 +154,5 @@ You can now tests the playbooks.
|
|||
## TODOs
|
||||
- Delete .torrents after X days
|
||||
- Add public keys to db (?)
|
||||
- Show public keys and link to .torrents on the website
|
||||
- Show public keys and link to .torrents on the website
|
||||
- Tuning elasticsearch indexing / analyzer
|
||||
|
|
|
@ -13,7 +13,7 @@ pcp_socket_dir = '/tmp'
|
|||
backend_hostname0 = 'localhost'
|
||||
backend_port0 = 5432
|
||||
backend_weight0 = 1
|
||||
backend_data_directory0 = '/var/lib/pgsql/data'
|
||||
backend_data_directory0 = '/var/lib/pgsql/9.6/data'
|
||||
backend_flag0 = 'ALLOW_TO_FAILOVER'
|
||||
# Controls various backend behavior
|
||||
# ALLOW_TO_FAILOVER or DISALLOW_TO_FAILOVER
|
||||
|
|
4
main.go
4
main.go
|
@ -32,8 +32,8 @@ func RunServer(conf *config.Config) {
|
|||
|
||||
// Set up server,
|
||||
srv := &http.Server{
|
||||
WriteTimeout: 5 * time.Second,
|
||||
ReadTimeout: 5 * time.Second,
|
||||
WriteTimeout: 30 * time.Second,
|
||||
ReadTimeout: 10 * time.Second,
|
||||
}
|
||||
l, err := network.CreateHTTPListener(conf)
|
||||
log.CheckError(err)
|
||||
|
|
|
@ -13,6 +13,13 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
TorrentStatusNormal = 1
|
||||
TorrentStatusRemake = 2
|
||||
TorrentStatusTrusted = 3
|
||||
TorrentStatusAPlus = 4
|
||||
)
|
||||
|
||||
type Feed struct {
|
||||
ID int
|
||||
Name string
|
||||
|
@ -76,7 +83,23 @@ func (t Torrent) Size() (s int) {
|
|||
}
|
||||
|
||||
func (t Torrent) TableName() string {
|
||||
return config.TableName
|
||||
return config.TorrentsTableName
|
||||
}
|
||||
|
||||
func (t Torrent) IsNormal() bool {
|
||||
return t.Status == TorrentStatusNormal
|
||||
}
|
||||
|
||||
func (t Torrent) IsRemake() bool {
|
||||
return t.Status == TorrentStatusRemake
|
||||
}
|
||||
|
||||
func (t Torrent) IsTrusted() bool {
|
||||
return t.Status == TorrentStatusTrusted
|
||||
}
|
||||
|
||||
func (t Torrent) IsAPlus() bool {
|
||||
return t.Status == TorrentStatusAPlus
|
||||
}
|
||||
|
||||
/* We need a JSON object instead of a Gorm structure because magnet URLs are
|
||||
|
@ -154,7 +177,7 @@ func (t *Torrent) ToJSON() TorrentJSON {
|
|||
}
|
||||
|
||||
// Sort file list by lowercase filename
|
||||
slice.Sort(fileListJSON, func (i, j int) bool {
|
||||
slice.Sort(fileListJSON, func(i, j int) bool {
|
||||
return strings.ToLower(fileListJSON[i].Path) < strings.ToLower(fileListJSON[j].Path)
|
||||
})
|
||||
|
||||
|
|
|
@ -4,17 +4,24 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
UserStatusBanned = -1
|
||||
UserStatusMember = 0
|
||||
UserStatusTrusted = 1
|
||||
UserStatusModerator = 2
|
||||
)
|
||||
|
||||
type User struct {
|
||||
ID uint `gorm:"column:user_id;primary_key"`
|
||||
Username string `gorm:"column:username"`
|
||||
Password string `gorm:"column:password"`
|
||||
Email string `gorm:"column:email"`
|
||||
Status int `gorm:"column:status"`
|
||||
CreatedAt time.Time `gorm:"column:created_at"`
|
||||
UpdatedAt time.Time `gorm:"column:updated_at"`
|
||||
ApiToken string `gorm:"column:api_token"`
|
||||
ApiTokenExpiry time.Time `gorm:"column:api_token_expiry"`
|
||||
Language string `gorm:"column:language"`
|
||||
ID uint `gorm:"column:user_id;primary_key"`
|
||||
Username string `gorm:"column:username"`
|
||||
Password string `gorm:"column:password"`
|
||||
Email string `gorm:"column:email"`
|
||||
Status int `gorm:"column:status"`
|
||||
CreatedAt time.Time `gorm:"column:created_at"`
|
||||
UpdatedAt time.Time `gorm:"column:updated_at"`
|
||||
ApiToken string `gorm:"column:api_token"`
|
||||
ApiTokenExpiry time.Time `gorm:"column:api_token_expiry"`
|
||||
Language string `gorm:"column:language"`
|
||||
|
||||
// TODO: move this to PublicUser
|
||||
LikingCount int `json:"likingCount" gorm:"-"`
|
||||
|
@ -50,6 +57,19 @@ func (u User) Size() (s int) {
|
|||
return
|
||||
}
|
||||
|
||||
func (u User) IsBanned() bool {
|
||||
return u.Status == UserStatusBanned
|
||||
}
|
||||
func (u User) IsMember() bool {
|
||||
return u.Status == UserStatusMember
|
||||
}
|
||||
func (u User) IsTrusted() bool {
|
||||
return u.Status == UserStatusTrusted
|
||||
}
|
||||
func (u User) IsModerator() bool {
|
||||
return u.Status == UserStatusModerator
|
||||
}
|
||||
|
||||
type PublicUser struct {
|
||||
User *User
|
||||
}
|
||||
|
|
|
@ -1,35 +1,35 @@
|
|||
/*Don't make changes to layout here, only colours*/
|
||||
/* Torrent status colors */
|
||||
.remake {
|
||||
background-color: #473e50; /*270,13%,28%*/
|
||||
background-color: #473e50; /*270,13%,28%*/
|
||||
}
|
||||
.trusted {
|
||||
background-color: #395045; /*150,17%,27%*/
|
||||
background-color: #395045; /*150,17%,27%*/
|
||||
}
|
||||
.aplus {
|
||||
background-color: #3c5b71; /*205,30%,34%*/
|
||||
background-color: #3c5b71; /*205,30%,34%*/
|
||||
}
|
||||
.remake a {
|
||||
color: #cfc2dc; /*270,26%,81%*/
|
||||
color: #cfc2dc; /*270,26%,81%*/
|
||||
}
|
||||
.trusted a {
|
||||
color: #bde0db; /*170,36%,81%*/
|
||||
color: #bde0db; /*170,36%,81%*/
|
||||
}
|
||||
.remake a:hover {
|
||||
color: #cf9fff;
|
||||
color: #cf9fff;
|
||||
}
|
||||
.trusted a:hover {
|
||||
color: #6ae3d1;
|
||||
color: #6ae3d1;
|
||||
}
|
||||
.table>tbody>tr>td, .table>tbody>tr>th, .table>tfoot>tr>td, .table>tfoot>tr>th, .table>thead>tr>td, .table>thead>tr>th {
|
||||
border-color: hsla(200,60%,70%,0.15);
|
||||
border-color: hsla(200,60%,70%,0.15);
|
||||
}
|
||||
|
||||
.pagination > li > a,
|
||||
.pagination > li > span {
|
||||
color: #fff;
|
||||
background-color: #b294bb;
|
||||
border-color: #b294bb;
|
||||
color: #fff;
|
||||
background-color: #b294bb;
|
||||
border-color: #b294bb;
|
||||
}
|
||||
|
||||
.pagination > .active > a,
|
||||
|
@ -38,14 +38,14 @@
|
|||
.pagination > .active > span,
|
||||
.pagination > .active > span:focus,
|
||||
.pagination > .active > span:hover {
|
||||
background-color: #a2c9dd;
|
||||
border-color: #a2c9dd;
|
||||
background-color: #a2c9dd;
|
||||
border-color: #a2c9dd;
|
||||
}
|
||||
|
||||
#mainmenu {
|
||||
background: #263238;
|
||||
color: #f2f2f2;
|
||||
border: 0px solid #263238;
|
||||
background: #263238;
|
||||
color: #f2f2f2;
|
||||
border: 0px solid #263238;
|
||||
}
|
||||
|
||||
#mainmenu a {
|
||||
|
@ -53,7 +53,7 @@
|
|||
}
|
||||
|
||||
#container {
|
||||
background-color: #29363d;
|
||||
background-color: #29363d;
|
||||
}
|
||||
|
||||
#mascot {
|
||||
|
@ -61,15 +61,15 @@
|
|||
}
|
||||
|
||||
body {
|
||||
background-color:#282A2E;
|
||||
color: #eff5f5;
|
||||
background-color:#282A2E;
|
||||
color: #eff5f5;
|
||||
}
|
||||
|
||||
|
||||
.pagination > .active > a {
|
||||
background: #ececec;
|
||||
border-color: #ececec;
|
||||
color: #337ab7; /* restore usual text color */
|
||||
background: #ececec;
|
||||
border-color: #ececec;
|
||||
color: #337ab7; /* restore usual text color */
|
||||
}
|
||||
|
||||
/* Links, Text */
|
||||
|
@ -81,18 +81,18 @@ a:hover {
|
|||
text-shadow: 1px 1px 0 #000;
|
||||
}
|
||||
.btn-success {
|
||||
color: #fff;
|
||||
background-color: #b294bb;
|
||||
border-color: #b294bb;
|
||||
color: #fff;
|
||||
background-color: #b294bb;
|
||||
border-color: #b294bb;
|
||||
}
|
||||
|
||||
:target {
|
||||
background-color: #b294bb;
|
||||
background-color: #b294bb;
|
||||
}
|
||||
|
||||
.form-control, pre {
|
||||
color: #fff;
|
||||
background-color: #29363d
|
||||
color: #fff;
|
||||
background-color: #29363d
|
||||
}
|
||||
|
||||
/* style the dropdown member menu */
|
||||
|
@ -105,54 +105,54 @@ a:hover {
|
|||
|
||||
/* Profile Content */
|
||||
.profile-content {
|
||||
background: #29363d;
|
||||
background: #29363d;
|
||||
}
|
||||
|
||||
/* Night mode switcher */
|
||||
#mainmenu a.nightswitch {
|
||||
background-image: url(/img/moon.png);
|
||||
background-image: url(/img/moon.png);
|
||||
}
|
||||
|
||||
/* Force images on description to fit width */
|
||||
#description img {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/* fix dark-on-dark */
|
||||
.captcha-container img {
|
||||
background: #fff;
|
||||
border-radius: .4em .4em 0 0;
|
||||
border-bottom: .5em solid #fff;
|
||||
margin-bottom: -.5em;
|
||||
background: #fff;
|
||||
border-radius: .4em .4em 0 0;
|
||||
border-bottom: .5em solid #fff;
|
||||
margin-bottom: -.5em;
|
||||
}
|
||||
.modal-content {
|
||||
background: #29363d;
|
||||
background: #29363d;
|
||||
}
|
||||
.modal-content .close {
|
||||
color: #fff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.text-error {
|
||||
background: #29363d;
|
||||
color: #cf9fff;
|
||||
background: #29363d;
|
||||
color: #cf9fff;
|
||||
}
|
||||
|
||||
/*Comments*/
|
||||
|
||||
.commentList .commentData {
|
||||
color: #fff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.commentList .commentBody {
|
||||
background: #29363d;
|
||||
color: #fff;
|
||||
background: #29363d;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
textarea.torrent-desc {
|
||||
background: none;
|
||||
background: none;
|
||||
}
|
||||
.md-editor>textarea:focus {
|
||||
background: none;
|
||||
}
|
||||
background: none;
|
||||
}
|
||||
|
|
|
@ -1,100 +1,100 @@
|
|||
/* Torrent status colors */
|
||||
.remake {
|
||||
background-color: rgb(240, 176, 128);
|
||||
background-color: rgb(240, 176, 128);
|
||||
}
|
||||
.trusted {
|
||||
background-color: #a3e9a4;
|
||||
background-color: #a3e9a4;
|
||||
}
|
||||
.aplus {
|
||||
background-color: #81d3fa;
|
||||
background-color: #81d3fa;
|
||||
}
|
||||
|
||||
.container.remake {
|
||||
box-shadow: 0px 0px 30px 10px rgba(240, 176, 128, 0.6);
|
||||
box-shadow: 0px 0px 30px 10px rgba(240, 176, 128, 0.6);
|
||||
}
|
||||
.row.remake {
|
||||
margin-bottom: 0.5rem;
|
||||
color: rgb(119, 94, 140);
|
||||
padding:2px 0;
|
||||
margin-bottom: 0.5rem;
|
||||
color: rgb(119, 94, 140);
|
||||
padding:2px 0;
|
||||
}
|
||||
.container.trusted {
|
||||
box-shadow: 0px 0px 30px 10px rgba(163, 233, 164, 0.6);
|
||||
box-shadow: 0px 0px 30px 10px rgba(163, 233, 164, 0.6);
|
||||
}
|
||||
.row.trusted {
|
||||
margin-bottom: 0.5rem;
|
||||
color: rgb(119, 94, 140);
|
||||
padding:2px 0;
|
||||
margin-bottom: 0.5rem;
|
||||
color: rgb(119, 94, 140);
|
||||
padding:2px 0;
|
||||
}
|
||||
.container.aplus {
|
||||
box-shadow: 0px 0px 30px 10px rgba(129, 211, 250, 0.6);
|
||||
box-shadow: 0px 0px 30px 10px rgba(129, 211, 250, 0.6);
|
||||
}
|
||||
.row.aplus {
|
||||
margin-bottom: 0.5rem;
|
||||
color: rgb(119, 94, 140);
|
||||
padding:2px 0;
|
||||
margin-bottom: 0.5rem;
|
||||
color: rgb(119, 94, 140);
|
||||
padding:2px 0;
|
||||
}
|
||||
|
||||
/* modified copy of NyaaTorrent theme */
|
||||
#mainmenu, #mainmenu .dropdown-menu{
|
||||
background: #263238;
|
||||
color: white;
|
||||
background: #263238;
|
||||
color: white;
|
||||
}
|
||||
#mainmenu {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
z-index: 4;
|
||||
border: 0px solid white;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
z-index: 4;
|
||||
border: 0px solid white;
|
||||
}
|
||||
#mainmenu a {
|
||||
background: none;
|
||||
color: white;
|
||||
background: none;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#mainmenu .divider {
|
||||
background: black;
|
||||
background: black;
|
||||
}
|
||||
|
||||
#container {
|
||||
padding-top: 1.25em;
|
||||
background: white;
|
||||
padding-top: 1.25em;
|
||||
background: white;
|
||||
}
|
||||
|
||||
#mascot {
|
||||
background-image: url(/img/renchon.png);
|
||||
width: 125px;
|
||||
height: 169px;
|
||||
position: fixed;
|
||||
bottom: 0px;
|
||||
left: 2%;
|
||||
position: fixed;
|
||||
bottom: 0px;
|
||||
left: 2%;
|
||||
}
|
||||
/* This used to avoid usage of Javascript for switching images. */
|
||||
|
||||
body {
|
||||
background-color: #ececec;
|
||||
color: #111111;
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #ececec;
|
||||
color: #111111;
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.torrentNav {
|
||||
text-align: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.pagination > .active > a {
|
||||
background: #ececec;
|
||||
border-color: #ececec;
|
||||
color: #337ab7; /* restore usual text color */
|
||||
background: #ececec;
|
||||
border-color: #ececec;
|
||||
color: #337ab7; /* restore usual text color */
|
||||
}
|
||||
|
||||
/* Links, Text */
|
||||
a {
|
||||
color: #106655;
|
||||
text-decoration : none;
|
||||
color: #106655;
|
||||
text-decoration : none;
|
||||
}
|
||||
|
||||
.download-btn {
|
||||
font-size: 24px;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.table-borderless > tbody > tr > td,
|
||||
|
@ -103,69 +103,69 @@ a {
|
|||
.table-borderless > tfoot > tr > th,
|
||||
.table-borderless > thead > tr > td,
|
||||
.table-borderless > thead > tr > th {
|
||||
border: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
td {
|
||||
text-overflow: ellipsis;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.torrent-info .name {
|
||||
font-weight: bold;
|
||||
overflow: hidden;
|
||||
padding-bottom: 3px;
|
||||
padding-top: 3px;
|
||||
word-wrap: break-word;
|
||||
font-weight: bold;
|
||||
overflow: hidden;
|
||||
padding-bottom: 3px;
|
||||
padding-top: 3px;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.torrent-hash {
|
||||
font-family: monospace;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.comment-row td:first-of-type {
|
||||
vertical-align: top;
|
||||
text-align: left;
|
||||
color:#bbb;
|
||||
vertical-align: top;
|
||||
text-align: left;
|
||||
color:#bbb;
|
||||
}
|
||||
|
||||
/* Table style & fixes */
|
||||
.table > tbody > tr > th, .nowrap {
|
||||
white-space: nowrap;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.table > tbody > tr > td {
|
||||
/* fix bootstrap uglyness */
|
||||
vertical-align: middle;
|
||||
/* fix bootstrap uglyness */
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.table > tbody > tr > th, .table > tbody > tr > td {
|
||||
padding: 4px;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.captcha-container {
|
||||
display: grid;
|
||||
grid-template-rows: auto;
|
||||
grid-template-columns: 240px;
|
||||
display: grid;
|
||||
grid-template-rows: auto;
|
||||
grid-template-columns: 240px;
|
||||
}
|
||||
|
||||
.custom-table-hover > tbody > tr:hover {
|
||||
opacity: 0.82;
|
||||
opacity: 0.82;
|
||||
}
|
||||
|
||||
.comment-row {
|
||||
border-top: 1px solid #ddd;
|
||||
border-top: 1px solid #ddd;
|
||||
}
|
||||
|
||||
th a:hover {
|
||||
text-decoration: none;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.sortarrowleft {
|
||||
letter-spacing: -0.6rem;
|
||||
letter-spacing: -0.6rem;
|
||||
}
|
||||
|
||||
.sortarrowdim {
|
||||
opacity: 0.25;
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
||||
div.container div.blockBody:nth-of-type(2) table{table-layout:fixed;}
|
||||
|
@ -176,272 +176,272 @@ div.container div.blockBody:nth-of-type(2) table tr:first-of-type th:last-of-typ
|
|||
|
||||
/* Mobile-friendly main table */
|
||||
@media only screen and (max-width: 700px) {
|
||||
table, thead, tbody, tr {
|
||||
display: block;
|
||||
}
|
||||
table, thead, tbody, tr {
|
||||
display: block;
|
||||
}
|
||||
|
||||
th {
|
||||
display: none;
|
||||
}
|
||||
th {
|
||||
display: none;
|
||||
}
|
||||
|
||||
td {
|
||||
display: inline-block;
|
||||
}
|
||||
td {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
td:nth-of-type(1), td:nth-of-type(2) {
|
||||
display: block;
|
||||
}
|
||||
td:nth-of-type(1), td:nth-of-type(2) {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.table > tbody > tr > td {
|
||||
border: none;
|
||||
}
|
||||
.table > tbody > tr > td {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Credit to bootsnipp.com for the css for the color graph */
|
||||
.colorgraph {
|
||||
height: 5px;
|
||||
border-top: 0;
|
||||
background: #c4e17f;
|
||||
border-radius: 5px;
|
||||
background-image: -webkit-linear-gradient(left, #c4e17f, #c4e17f 12.5%, #f7fdca 12.5%, #f7fdca 25%, #fecf71 25%, #fecf71 37.5%, #f0776c 37.5%, #f0776c 50%, #db9dbe 50%, #db9dbe 62.5%, #c49cde 62.5%, #c49cde 75%, #669ae1 75%, #669ae1 87.5%, #62c2e4 87.5%, #62c2e4);
|
||||
background-image: -moz-linear-gradient(left, #c4e17f, #c4e17f 12.5%, #f7fdca 12.5%, #f7fdca 25%, #fecf71 25%, #fecf71 37.5%, #f0776c 37.5%, #f0776c 50%, #db9dbe 50%, #db9dbe 62.5%, #c49cde 62.5%, #c49cde 75%, #669ae1 75%, #669ae1 87.5%, #62c2e4 87.5%, #62c2e4);
|
||||
background-image: -o-linear-gradient(left, #c4e17f, #c4e17f 12.5%, #f7fdca 12.5%, #f7fdca 25%, #fecf71 25%, #fecf71 37.5%, #f0776c 37.5%, #f0776c 50%, #db9dbe 50%, #db9dbe 62.5%, #c49cde 62.5%, #c49cde 75%, #669ae1 75%, #669ae1 87.5%, #62c2e4 87.5%, #62c2e4);
|
||||
background-image: linear-gradient(to right, #c4e17f, #c4e17f 12.5%, #f7fdca 12.5%, #f7fdca 25%, #fecf71 25%, #fecf71 37.5%, #f0776c 37.5%, #f0776c 50%, #db9dbe 50%, #db9dbe 62.5%, #c49cde 62.5%, #c49cde 75%, #669ae1 75%, #669ae1 87.5%, #62c2e4 87.5%, #62c2e4);
|
||||
height: 5px;
|
||||
border-top: 0;
|
||||
background: #c4e17f;
|
||||
border-radius: 5px;
|
||||
background-image: -webkit-linear-gradient(left, #c4e17f, #c4e17f 12.5%, #f7fdca 12.5%, #f7fdca 25%, #fecf71 25%, #fecf71 37.5%, #f0776c 37.5%, #f0776c 50%, #db9dbe 50%, #db9dbe 62.5%, #c49cde 62.5%, #c49cde 75%, #669ae1 75%, #669ae1 87.5%, #62c2e4 87.5%, #62c2e4);
|
||||
background-image: -moz-linear-gradient(left, #c4e17f, #c4e17f 12.5%, #f7fdca 12.5%, #f7fdca 25%, #fecf71 25%, #fecf71 37.5%, #f0776c 37.5%, #f0776c 50%, #db9dbe 50%, #db9dbe 62.5%, #c49cde 62.5%, #c49cde 75%, #669ae1 75%, #669ae1 87.5%, #62c2e4 87.5%, #62c2e4);
|
||||
background-image: -o-linear-gradient(left, #c4e17f, #c4e17f 12.5%, #f7fdca 12.5%, #f7fdca 25%, #fecf71 25%, #fecf71 37.5%, #f0776c 37.5%, #f0776c 50%, #db9dbe 50%, #db9dbe 62.5%, #c49cde 62.5%, #c49cde 75%, #669ae1 75%, #669ae1 87.5%, #62c2e4 87.5%, #62c2e4);
|
||||
background-image: linear-gradient(to right, #c4e17f, #c4e17f 12.5%, #f7fdca 12.5%, #f7fdca 25%, #fecf71 25%, #fecf71 37.5%, #f0776c 37.5%, #f0776c 50%, #db9dbe 50%, #db9dbe 62.5%, #c49cde 62.5%, #c49cde 75%, #669ae1 75%, #669ae1 87.5%, #62c2e4 87.5%, #62c2e4);
|
||||
}
|
||||
|
||||
.center-image {
|
||||
max-width: 100%;
|
||||
max-height: 80vh;
|
||||
max-width: 100%;
|
||||
max-height: 80vh;
|
||||
}
|
||||
|
||||
/* the curved edges triggered my autism */
|
||||
.navbar {
|
||||
border-radius: 0px;
|
||||
border-radius: 0px;
|
||||
}
|
||||
/* the logo needs some space */
|
||||
.navbar-logo {
|
||||
margin-right: 10px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
:target {
|
||||
background-color: #e5eecc;
|
||||
background-color: #e5eecc;
|
||||
}
|
||||
|
||||
#mainmenu button .search_text {
|
||||
display: none;
|
||||
display: none;
|
||||
}
|
||||
#mainmenu .navbar-form select.form-control
|
||||
{
|
||||
width: 12rem;
|
||||
width: 12rem;
|
||||
}
|
||||
#mainmenu .navbar-form select.form-control#max
|
||||
{
|
||||
width: 6rem;
|
||||
width: 6rem;
|
||||
}
|
||||
|
||||
.special-img
|
||||
{
|
||||
position: relative;
|
||||
top: -5px;
|
||||
float: left;
|
||||
left: -5px;
|
||||
position: relative;
|
||||
top: -5px;
|
||||
float: left;
|
||||
left: -5px;
|
||||
}
|
||||
|
||||
#mainmenu .badgemenu .profile-image {
|
||||
line-height: 35px;
|
||||
line-height: 35px;
|
||||
}
|
||||
|
||||
#mainmenu .navbar-header, #mainmenu .navbar-nav, #mainmenu .navbar-form {
|
||||
padding-top: 10px;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
#mainmenu .badgemenu {
|
||||
padding-top: 0;
|
||||
margin-right: -50px; /* don't ask */
|
||||
padding-top: 0;
|
||||
margin-right: -50px; /* don't ask */
|
||||
}
|
||||
|
||||
/* PROFILE PAGE */
|
||||
/* Profile container */
|
||||
.profile {
|
||||
margin: 20px 0;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
/* Profile sidebar */
|
||||
.profile-sidebar {
|
||||
padding: 20px 0 10px 0;
|
||||
background: #182430;
|
||||
padding: 20px 0 10px 0;
|
||||
background: #182430;
|
||||
}
|
||||
|
||||
.profile-userpic img {
|
||||
float: none;
|
||||
margin: 0 auto;
|
||||
width: 50%;
|
||||
height: 50%;
|
||||
-webkit-border-radius: 50% !important;
|
||||
-moz-border-radius: 50% !important;
|
||||
border-radius: 50% !important;
|
||||
float: none;
|
||||
margin: 0 auto;
|
||||
width: 50%;
|
||||
height: 50%;
|
||||
-webkit-border-radius: 50% !important;
|
||||
-moz-border-radius: 50% !important;
|
||||
border-radius: 50% !important;
|
||||
}
|
||||
|
||||
.profile-usertitle {
|
||||
text-align: center;
|
||||
margin-top: 20px;
|
||||
text-align: center;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.profile-usertitle-name {
|
||||
color: #5a7391;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 7px;
|
||||
color: #5a7391;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 7px;
|
||||
}
|
||||
|
||||
.profile-usertitle-job {
|
||||
text-transform: uppercase;
|
||||
color: #5b9bd1;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 15px;
|
||||
text-transform: uppercase;
|
||||
color: #5b9bd1;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.profile-userbuttons {
|
||||
text-align: center;
|
||||
margin-top: 10px;
|
||||
text-align: center;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.profile-userbuttons .btn {
|
||||
text-transform: uppercase;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
padding: 6px 15px;
|
||||
margin-right: 5px;
|
||||
text-transform: uppercase;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
padding: 6px 15px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.profile-userbuttons .btn:last-child {
|
||||
margin-right: 0px;
|
||||
margin-right: 0px;
|
||||
}
|
||||
|
||||
|
||||
.profile-usermenu {
|
||||
margin-top: 30px;
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.profile-usermenu ul li {
|
||||
border-bottom: 1px solid #f0f4f7;
|
||||
border-bottom: 1px solid #f0f4f7;
|
||||
}
|
||||
|
||||
.profile-usermenu ul li:last-child {
|
||||
border-bottom: none;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.profile-usermenu ul li a {
|
||||
color: #93a3b5;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #93a3b5;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.profile-usermenu ul li a i {
|
||||
margin-right: 8px;
|
||||
font-size: 14px;
|
||||
margin-right: 8px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.profile-usermenu ul li a:hover {
|
||||
background-color: #fafcfd;
|
||||
color: #5b9bd1;
|
||||
background-color: #fafcfd;
|
||||
color: #5b9bd1;
|
||||
}
|
||||
|
||||
.profile-usermenu ul li.active {
|
||||
border-bottom: none;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.profile-usermenu ul li.active a {
|
||||
color: #5b9bd1;
|
||||
background-color: #f6f9fb;
|
||||
border-left: 2px solid #5b9bd1;
|
||||
margin-left: -2px;
|
||||
color: #5b9bd1;
|
||||
background-color: #f6f9fb;
|
||||
border-left: 2px solid #5b9bd1;
|
||||
margin-left: -2px;
|
||||
}
|
||||
|
||||
/* Profile Content */
|
||||
.profile-content {
|
||||
padding: 20px;
|
||||
background: #fff;
|
||||
min-height: 460px;
|
||||
padding: 20px;
|
||||
background: #fff;
|
||||
min-height: 460px;
|
||||
}
|
||||
|
||||
/* Night mode switcher */
|
||||
#mainmenu a.nightswitch {
|
||||
background: transparent url(/img/sun.png) no-repeat;
|
||||
background-size: 24px;
|
||||
margin-top: 10px;
|
||||
margin-left: 3px;
|
||||
width: 24px;
|
||||
background: transparent url(/img/sun.png) no-repeat;
|
||||
background-size: 24px;
|
||||
margin-top: 10px;
|
||||
margin-left: 3px;
|
||||
width: 24px;
|
||||
}
|
||||
|
||||
footer {
|
||||
text-align: center;
|
||||
padding-bottom: 2rem;
|
||||
font-size: 2rem;
|
||||
font-family: cursive;
|
||||
color: #616161;
|
||||
text-shadow: -1px -1px #999999;
|
||||
text-align: center;
|
||||
padding-bottom: 2rem;
|
||||
font-size: 2rem;
|
||||
font-family: cursive;
|
||||
color: #616161;
|
||||
text-shadow: -1px -1px #999999;
|
||||
}
|
||||
|
||||
select#bottom_language_selector {
|
||||
width: 20%;
|
||||
margin: auto;
|
||||
margin-bottom: 2rem;
|
||||
width: 20%;
|
||||
margin: auto;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
/* Force images on description to fit width */
|
||||
#description img {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/* Psuedo green-text fuckery. */
|
||||
#comments blockquote {
|
||||
color: #789922;
|
||||
color: #789922;
|
||||
}
|
||||
#comments blockquote:before {
|
||||
content: ">";
|
||||
content: ">";
|
||||
}
|
||||
|
||||
.completed {
|
||||
font-size: 2rem;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
font-size: 2rem;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.proSeedBar {
|
||||
width:100%; height: 0.5rem; overflow: hidden;
|
||||
width:100%; height: 0.5rem; overflow: hidden;
|
||||
}
|
||||
|
||||
.proSeedBar .seeds {
|
||||
background: green;
|
||||
height: 0.5rem;
|
||||
background: green;
|
||||
height: 0.5rem;
|
||||
}
|
||||
|
||||
.proSeedBar .leechs {
|
||||
height: 0.5rem;
|
||||
background: red;
|
||||
position: relative;
|
||||
top: -0.5rem;
|
||||
float: right;
|
||||
height: 0.5rem;
|
||||
background: red;
|
||||
position: relative;
|
||||
top: -0.5rem;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.comment-date {
|
||||
font-size: smaller;
|
||||
width: auto; /* Undo bootstrap's fixed width */
|
||||
font-size: smaller;
|
||||
width: auto; /* Undo bootstrap's fixed width */
|
||||
}
|
||||
|
||||
.text-error {
|
||||
background: white;
|
||||
color: #cf9fff;
|
||||
background: white;
|
||||
color: #cf9fff;
|
||||
}
|
||||
|
||||
/* Wordbreak fix*/
|
||||
|
||||
.break {
|
||||
word-break: break-all;
|
||||
hyphens: auto;
|
||||
word-break: break-all;
|
||||
hyphens: auto;
|
||||
}
|
||||
|
||||
.filelist-control {
|
||||
|
@ -453,39 +453,39 @@ select#bottom_language_selector {
|
|||
}
|
||||
|
||||
.filelist-control[aria-expanded="true"]::before {
|
||||
content: "\25BC ";
|
||||
content: "\25BC ";
|
||||
}
|
||||
|
||||
/*Comments*/
|
||||
|
||||
.commentList::before,
|
||||
.commentList::after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.commentList ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.commentList img {
|
||||
opacity: 1;
|
||||
filter: Alpha(opacity=100);
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
-o-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
opacity: 1;
|
||||
filter: Alpha(opacity=100);
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
-o-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.commentList img.avatar {
|
||||
position: relative;
|
||||
float: left;
|
||||
margin-left: 0;
|
||||
margin-top: 0;
|
||||
width: 65px;
|
||||
height: 65px;
|
||||
position: relative;
|
||||
float: left;
|
||||
margin-left: 0;
|
||||
margin-top: 0;
|
||||
width: 65px;
|
||||
height: 65px;
|
||||
}
|
||||
|
||||
.commentList .commentBody {
|
||||
|
@ -500,77 +500,77 @@ select#bottom_language_selector {
|
|||
}
|
||||
|
||||
.commentList .commentBody > .row > div {
|
||||
word-wrap: break-word;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.commentList .commentData {
|
||||
font-size: 13px;
|
||||
margin-bottom: 10px !important;
|
||||
border-bottom: 1px solid #eee;
|
||||
height: 2.2em;
|
||||
font-size: 13px;
|
||||
margin-bottom: 10px !important;
|
||||
border-bottom: 1px solid #eee;
|
||||
height: 2.2em;
|
||||
}
|
||||
|
||||
.commentList ul.comments ul{
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
margin-left: 85px;
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
margin-left: 85px;
|
||||
}
|
||||
|
||||
|
||||
.commentList h3 {
|
||||
margin-bottom: 40px;
|
||||
font-size: 26px;
|
||||
line-height: 30px;
|
||||
font-weight: 800;
|
||||
margin-bottom: 40px;
|
||||
font-size: 26px;
|
||||
line-height: 30px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.comment {
|
||||
padding: 1em;
|
||||
width: 75%;
|
||||
margin-left: 12%;
|
||||
padding: 1em;
|
||||
width: 75%;
|
||||
margin-left: 12%;
|
||||
}
|
||||
|
||||
@media only screen and (min-device-width : 320px) and (max-device-width : 480px) {
|
||||
|
||||
.comment {
|
||||
width: 100%;
|
||||
margin-left: 0;
|
||||
}
|
||||
.comment {
|
||||
width: 100%;
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 995px) {
|
||||
.navbar-header {
|
||||
float: none;
|
||||
}
|
||||
.navbar-left,.navbar-right {
|
||||
float: none !important;
|
||||
}
|
||||
.navbar-toggle {
|
||||
display: block;
|
||||
}
|
||||
.navbar-collapse {
|
||||
border-top: 1px solid transparent;
|
||||
box-shadow: inset 0 1px 0 rgba(255,255,255,0.1);
|
||||
}
|
||||
.navbar-fixed-top {
|
||||
.navbar-header {
|
||||
float: none;
|
||||
}
|
||||
.navbar-left,.navbar-right {
|
||||
float: none !important;
|
||||
}
|
||||
.navbar-toggle {
|
||||
display: block;
|
||||
}
|
||||
.navbar-collapse {
|
||||
border-top: 1px solid transparent;
|
||||
box-shadow: inset 0 1px 0 rgba(255,255,255,0.1);
|
||||
}
|
||||
.navbar-fixed-top {
|
||||
top: 0;
|
||||
border-width: 0 0 1px;
|
||||
}
|
||||
.navbar-collapse.collapse {
|
||||
display: none!important;
|
||||
}
|
||||
.navbar-nav {
|
||||
float: none!important;
|
||||
.navbar-collapse.collapse {
|
||||
display: none!important;
|
||||
}
|
||||
.navbar-nav {
|
||||
float: none!important;
|
||||
margin-top: 7.5px;
|
||||
}
|
||||
.navbar-nav>li {
|
||||
float: none;
|
||||
}
|
||||
.navbar-nav>li>a {
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
.collapse.in{
|
||||
display:block !important;
|
||||
float: none;
|
||||
}
|
||||
}
|
||||
.navbar-nav>li>a {
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
.collapse.in{
|
||||
display:block !important;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,29 +4,29 @@ function loadLanguages() {
|
|||
if (xhr.readyState == 4 && xhr.status == 200) {
|
||||
var selector = document.getElementById("bottom_language_selector");
|
||||
selector.hidden = false
|
||||
/* Response format is
|
||||
* { "current": "(user current language)",
|
||||
* "languages": {
|
||||
* "(language_code)": "(language_name"),
|
||||
* }} */
|
||||
var response = JSON.parse(xhr.responseText);
|
||||
/* Response format is
|
||||
* { "current": "(user current language)",
|
||||
* "languages": {
|
||||
* "(language_code)": "(language_name"),
|
||||
* }} */
|
||||
var response = JSON.parse(xhr.responseText);
|
||||
for (var language in response.languages) {
|
||||
if (!response.languages.hasOwnProperty(language)) continue;
|
||||
|
||||
var opt = document.createElement("option")
|
||||
opt.value = language
|
||||
opt.innerHTML = response.languages[language]
|
||||
if (language == response.current) {
|
||||
opt.selected = true
|
||||
}
|
||||
opt.value = language
|
||||
opt.innerHTML = response.languages[language]
|
||||
if (language == response.current) {
|
||||
opt.selected = true
|
||||
}
|
||||
|
||||
selector.appendChild(opt)
|
||||
}
|
||||
}
|
||||
}
|
||||
xhr.open("GET", "/language", true)
|
||||
xhr.setRequestHeader("Content-Type", "application/json")
|
||||
xhr.send()
|
||||
xhr.setRequestHeader("Content-Type", "application/json")
|
||||
xhr.send()
|
||||
}
|
||||
|
||||
loadLanguages();
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
function toggleNightMode() {
|
||||
var night = localStorage.getItem("night");
|
||||
if(night == "true") {
|
||||
document.getElementsByTagName("head")[0].removeChild(darkStyleLink);
|
||||
} else {
|
||||
document.getElementsByTagName("head")[0].appendChild(darkStyleLink);
|
||||
}
|
||||
localStorage.setItem("night", (night == "true") ? "false" : "true");
|
||||
var night = localStorage.getItem("night");
|
||||
if(night == "true") {
|
||||
document.getElementsByTagName("head")[0].removeChild(darkStyleLink);
|
||||
} else {
|
||||
document.getElementsByTagName("head")[0].appendChild(darkStyleLink);
|
||||
}
|
||||
localStorage.setItem("night", (night == "true") ? "false" : "true");
|
||||
}
|
||||
|
||||
// Used by spoiler tags
|
||||
|
@ -41,17 +41,17 @@ $(".date-comments").each(function(index, el) {
|
|||
});
|
||||
/*Fixed-Navbar offset fix*/
|
||||
window.onload = function() {
|
||||
var shiftWindow = function() { scrollBy(0, -70) };
|
||||
if (location.hash) shiftWindow();
|
||||
window.addEventListener("hashchange", shiftWindow);
|
||||
var shiftWindow = function() { scrollBy(0, -70) };
|
||||
if (location.hash) shiftWindow();
|
||||
window.addEventListener("hashchange", shiftWindow);
|
||||
};
|
||||
|
||||
|
||||
$('#mascot').bind('touchstart mousedown click', function(e){
|
||||
var night = localStorage.getItem("night");
|
||||
if(night == "true") {
|
||||
if(night == "true") {
|
||||
$('#explosion')[0].play();
|
||||
} else {
|
||||
} else {
|
||||
$('#nyaapassu')[0].play();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,67 +1,67 @@
|
|||
$(function () {
|
||||
$('.button-checkbox').each(function () {
|
||||
$('.button-checkbox').each(function () {
|
||||
|
||||
// Settings
|
||||
var $widget = $(this),
|
||||
$button = $widget.find('button'),
|
||||
$checkbox = $widget.find('input:checkbox'),
|
||||
color = $button.data('color'),
|
||||
settings = {
|
||||
on: {
|
||||
icon: 'glyphicon glyphicon-check'
|
||||
},
|
||||
off: {
|
||||
icon: 'glyphicon glyphicon-unchecked'
|
||||
}
|
||||
};
|
||||
// Settings
|
||||
var $widget = $(this),
|
||||
$button = $widget.find('button'),
|
||||
$checkbox = $widget.find('input:checkbox'),
|
||||
color = $button.data('color'),
|
||||
settings = {
|
||||
on: {
|
||||
icon: 'glyphicon glyphicon-check'
|
||||
},
|
||||
off: {
|
||||
icon: 'glyphicon glyphicon-unchecked'
|
||||
}
|
||||
};
|
||||
|
||||
// Event Handlers
|
||||
$button.on('click', function () {
|
||||
$checkbox.prop('checked', !$checkbox.is(':checked'));
|
||||
$checkbox.triggerHandler('change');
|
||||
updateDisplay();
|
||||
});
|
||||
$checkbox.on('change', function () {
|
||||
updateDisplay();
|
||||
});
|
||||
// Event Handlers
|
||||
$button.on('click', function () {
|
||||
$checkbox.prop('checked', !$checkbox.is(':checked'));
|
||||
$checkbox.triggerHandler('change');
|
||||
updateDisplay();
|
||||
});
|
||||
$checkbox.on('change', function () {
|
||||
updateDisplay();
|
||||
});
|
||||
|
||||
// Actions
|
||||
function updateDisplay() {
|
||||
$checkbox.addClass("hidden")
|
||||
$button.removeClass("hidden")
|
||||
var isChecked = $checkbox.is(':checked');
|
||||
// Actions
|
||||
function updateDisplay() {
|
||||
$checkbox.addClass("hidden")
|
||||
$button.removeClass("hidden")
|
||||
var isChecked = $checkbox.is(':checked');
|
||||
|
||||
// Set the button's state
|
||||
$button.data('state', (isChecked) ? "on" : "off");
|
||||
// Set the button's state
|
||||
$button.data('state', (isChecked) ? "on" : "off");
|
||||
|
||||
// Set the button's icon
|
||||
$button.find('.state-icon')
|
||||
.removeClass()
|
||||
.addClass('state-icon ' + settings[$button.data('state')].icon);
|
||||
// Set the button's icon
|
||||
$button.find('.state-icon')
|
||||
.removeClass()
|
||||
.addClass('state-icon ' + settings[$button.data('state')].icon);
|
||||
|
||||
// Update the button's color
|
||||
if (isChecked) {
|
||||
$button
|
||||
.removeClass('btn-default')
|
||||
.addClass('btn-' + color + ' active');
|
||||
}
|
||||
else {
|
||||
$button
|
||||
.removeClass('btn-' + color + ' active')
|
||||
.addClass('btn-default');
|
||||
}
|
||||
}
|
||||
// Update the button's color
|
||||
if (isChecked) {
|
||||
$button
|
||||
.removeClass('btn-default')
|
||||
.addClass('btn-' + color + ' active');
|
||||
}
|
||||
else {
|
||||
$button
|
||||
.removeClass('btn-' + color + ' active')
|
||||
.addClass('btn-default');
|
||||
}
|
||||
}
|
||||
|
||||
// Initialization
|
||||
function init() {
|
||||
// Initialization
|
||||
function init() {
|
||||
|
||||
updateDisplay();
|
||||
updateDisplay();
|
||||
|
||||
// Inject the icon if applicable
|
||||
if ($button.find('.state-icon').length == 0) {
|
||||
$button.prepend('<i class="state-icon ' + settings[$button.data('state')].icon + '"></i>');
|
||||
}
|
||||
}
|
||||
init();
|
||||
});
|
||||
});
|
||||
// Inject the icon if applicable
|
||||
if ($button.find('.state-icon').length == 0) {
|
||||
$button.prepend('<i class="state-icon ' + settings[$button.data('state')].icon + '"></i>');
|
||||
}
|
||||
}
|
||||
init();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
(function() {
|
||||
var torrent = $("input[name=torrent]"),
|
||||
magnet = $("input[name=magnet]"),
|
||||
name = $("input[name=name]");
|
||||
magnet = $("input[name=magnet]"),
|
||||
name = $("input[name=name]");
|
||||
|
||||
torrent.on("change", function() {
|
||||
if (torrent.val() == "") {
|
||||
|
|
|
@ -14,6 +14,7 @@ import (
|
|||
"github.com/NyaaPantsu/nyaa/model"
|
||||
"github.com/NyaaPantsu/nyaa/service"
|
||||
"github.com/NyaaPantsu/nyaa/service/api"
|
||||
"github.com/NyaaPantsu/nyaa/service/upload"
|
||||
"github.com/NyaaPantsu/nyaa/service/torrent"
|
||||
"github.com/NyaaPantsu/nyaa/util"
|
||||
"github.com/NyaaPantsu/nyaa/util/log"
|
||||
|
@ -36,7 +37,7 @@ func ApiHandler(w http.ResponseWriter, r *http.Request) {
|
|||
if req.MaxPerPage == 0 {
|
||||
req.MaxPerPage = config.TorrentsPerPage
|
||||
}
|
||||
if req.Page == 0 {
|
||||
if req.Page <= 0 {
|
||||
req.Page = 1
|
||||
}
|
||||
|
||||
|
@ -60,6 +61,10 @@ func ApiHandler(w http.ResponseWriter, r *http.Request) {
|
|||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if req.Page <= 0 {
|
||||
NotFoundHandler(w, r)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,22 +106,12 @@ func ApiUploadHandler(w http.ResponseWriter, r *http.Request) {
|
|||
token := r.Header.Get("Authorization")
|
||||
user := model.User{}
|
||||
db.ORM.Where("api_token = ?", token).First(&user) //i don't like this
|
||||
|
||||
if config.UploadsDisabled {
|
||||
|
||||
if config.AdminsAreStillAllowedTo && user.Status != 2 && config.TrustedUsersAreStillAllowedTo && user.Status != 1 {
|
||||
http.Error(w, "Error uploads are disabled", http.StatusBadRequest)
|
||||
return
|
||||
} else if !config.AdminsAreStillAllowedTo && user.Status == 2 {
|
||||
http.Error(w, "Error uploads are disabled", http.StatusBadRequest)
|
||||
return
|
||||
} else if !config.TrustedUsersAreStillAllowedTo && user.Status == 1 {
|
||||
http.Error(w, "Error uploads are disabled", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
if !uploadService.IsUploadEnabled(user) {
|
||||
http.Error(w, "Error uploads are disabled", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
if user.ID == 0 {
|
||||
http.Error(w, apiService.ErrApiKey.Error(), http.StatusUnauthorized)
|
||||
return
|
||||
|
@ -194,20 +189,10 @@ func ApiUpdateHandler(w http.ResponseWriter, r *http.Request) {
|
|||
token := r.Header.Get("Authorization")
|
||||
user := model.User{}
|
||||
db.ORM.Where("api_token = ?", token).First(&user) //i don't like this
|
||||
|
||||
if config.UploadsDisabled {
|
||||
|
||||
if config.AdminsAreStillAllowedTo && user.Status != 2 && config.TrustedUsersAreStillAllowedTo && user.Status != 1 {
|
||||
http.Error(w, "Error uploads are disabled", http.StatusInternalServerError)
|
||||
return
|
||||
} else if !config.AdminsAreStillAllowedTo && user.Status == 2 {
|
||||
http.Error(w, "Error uploads are disabled", http.StatusInternalServerError)
|
||||
return
|
||||
} else if !config.TrustedUsersAreStillAllowedTo && user.Status == 1 {
|
||||
http.Error(w, "Error uploads are disabled", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
if !uploadService.IsUploadEnabled(user) {
|
||||
http.Error(w, "Error uploads are disabled", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
contentType := r.Header.Get("Content-Type")
|
||||
|
|
|
@ -37,6 +37,10 @@ func HomeHandler(w http.ResponseWriter, r *http.Request) {
|
|||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if pagenum <= 0 {
|
||||
NotFoundHandler(w, r)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
search := common.SearchParam{
|
||||
|
|
|
@ -15,7 +15,6 @@ import (
|
|||
"github.com/NyaaPantsu/nyaa/service/torrent"
|
||||
"github.com/NyaaPantsu/nyaa/service/user"
|
||||
form "github.com/NyaaPantsu/nyaa/service/user/form"
|
||||
"github.com/NyaaPantsu/nyaa/service/user/permission"
|
||||
"github.com/NyaaPantsu/nyaa/util/languages"
|
||||
"github.com/NyaaPantsu/nyaa/util/log"
|
||||
"github.com/NyaaPantsu/nyaa/util/search"
|
||||
|
@ -107,178 +106,149 @@ func NewPanelSearchForm() SearchForm {
|
|||
}
|
||||
|
||||
func IndexModPanel(w http.ResponseWriter, r *http.Request) {
|
||||
// FIXME WrapModHandler already get user from db
|
||||
currentUser := GetUser(r)
|
||||
if userPermission.HasAdmin(currentUser) {
|
||||
offset := 10
|
||||
offset := 10
|
||||
|
||||
torrents, _, _ := torrentService.GetAllTorrents(offset, 0)
|
||||
users, _ := userService.RetrieveUsersForAdmin(offset, 0)
|
||||
comments, _ := commentService.GetAllComments(offset, 0, "", "")
|
||||
torrentReports, _, _ := reportService.GetAllTorrentReports(offset, 0)
|
||||
torrents, _, _ := torrentService.GetAllTorrents(offset, 0)
|
||||
users, _ := userService.RetrieveUsersForAdmin(offset, 0)
|
||||
comments, _ := commentService.GetAllComments(offset, 0, "", "")
|
||||
torrentReports, _, _ := reportService.GetAllTorrentReports(offset, 0)
|
||||
|
||||
languages.SetTranslationFromRequest(panelIndex, r)
|
||||
htv := PanelIndexVbs{torrents, model.TorrentReportsToJSON(torrentReports), users, comments, NewPanelSearchForm(), currentUser, r.URL}
|
||||
err := panelIndex.ExecuteTemplate(w, "admin_index.html", htv)
|
||||
log.CheckError(err)
|
||||
} else {
|
||||
http.Error(w, "admins only", http.StatusForbidden)
|
||||
}
|
||||
languages.SetTranslationFromRequest(panelIndex, r)
|
||||
htv := PanelIndexVbs{torrents, model.TorrentReportsToJSON(torrentReports), users, comments, NewPanelSearchForm(), currentUser, r.URL}
|
||||
err := panelIndex.ExecuteTemplate(w, "admin_index.html", htv)
|
||||
log.CheckError(err)
|
||||
}
|
||||
|
||||
func TorrentsListPanel(w http.ResponseWriter, r *http.Request) {
|
||||
currentUser := GetUser(r)
|
||||
if userPermission.HasAdmin(currentUser) {
|
||||
vars := mux.Vars(r)
|
||||
page := vars["page"]
|
||||
vars := mux.Vars(r)
|
||||
page := vars["page"]
|
||||
|
||||
var err error
|
||||
pagenum := 1
|
||||
if page != "" {
|
||||
pagenum, err = strconv.Atoi(html.EscapeString(page))
|
||||
if !log.CheckError(err) {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
var err error
|
||||
pagenum := 1
|
||||
if page != "" {
|
||||
pagenum, err = strconv.Atoi(html.EscapeString(page))
|
||||
if !log.CheckError(err) {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
offset := 100
|
||||
|
||||
searchParam, torrents, _, err := search.SearchByQuery(r, pagenum)
|
||||
searchForm := SearchForm{
|
||||
SearchParam: searchParam,
|
||||
Category: searchParam.Category.String(),
|
||||
ShowItemsPerPage: true,
|
||||
}
|
||||
|
||||
languages.SetTranslationFromRequest(panelTorrentList, r)
|
||||
htv := PanelTorrentListVbs{torrents, searchForm, Navigation{int(searchParam.Max), offset, pagenum, "mod_tlist_page"}, currentUser, r.URL}
|
||||
err = panelTorrentList.ExecuteTemplate(w, "admin_index.html", htv)
|
||||
log.CheckError(err)
|
||||
} else {
|
||||
|
||||
http.Error(w, "admins only", http.StatusForbidden)
|
||||
}
|
||||
offset := 100
|
||||
|
||||
searchParam, torrents, _, err := search.SearchByQuery(r, pagenum)
|
||||
searchForm := SearchForm{
|
||||
SearchParam: searchParam,
|
||||
Category: searchParam.Category.String(),
|
||||
ShowItemsPerPage: true,
|
||||
}
|
||||
|
||||
languages.SetTranslationFromRequest(panelTorrentList, r)
|
||||
navigation := Navigation{int(searchParam.Max), offset, pagenum, "mod_tlist_page"}
|
||||
ptlv := PanelTorrentListVbs{torrents, searchForm, navigation, currentUser, r.URL}
|
||||
err = panelTorrentList.ExecuteTemplate(w, "admin_index.html", ptlv)
|
||||
log.CheckError(err)
|
||||
}
|
||||
|
||||
func TorrentReportListPanel(w http.ResponseWriter, r *http.Request) {
|
||||
currentUser := GetUser(r)
|
||||
if userPermission.HasAdmin(currentUser) {
|
||||
vars := mux.Vars(r)
|
||||
page := vars["page"]
|
||||
vars := mux.Vars(r)
|
||||
page := vars["page"]
|
||||
|
||||
var err error
|
||||
pagenum := 1
|
||||
if page != "" {
|
||||
pagenum, err = strconv.Atoi(html.EscapeString(page))
|
||||
if !log.CheckError(err) {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
var err error
|
||||
pagenum := 1
|
||||
if page != "" {
|
||||
pagenum, err = strconv.Atoi(html.EscapeString(page))
|
||||
if !log.CheckError(err) {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
offset := 100
|
||||
|
||||
torrentReports, nbReports, _ := reportService.GetAllTorrentReports(offset, (pagenum-1)*offset)
|
||||
|
||||
reportJSON := model.TorrentReportsToJSON(torrentReports)
|
||||
languages.SetTranslationFromRequest(panelTorrentReportList, r)
|
||||
htv := PanelTorrentReportListVbs{reportJSON, NewSearchForm(), Navigation{nbReports, offset, pagenum, "mod_trlist_page"}, currentUser, r.URL}
|
||||
err = panelTorrentReportList.ExecuteTemplate(w, "admin_index.html", htv)
|
||||
log.CheckError(err)
|
||||
} else {
|
||||
http.Error(w, "admins only", http.StatusForbidden)
|
||||
}
|
||||
offset := 100
|
||||
|
||||
torrentReports, nbReports, _ := reportService.GetAllTorrentReports(offset, (pagenum-1)*offset)
|
||||
|
||||
reportJSON := model.TorrentReportsToJSON(torrentReports)
|
||||
languages.SetTranslationFromRequest(panelTorrentReportList, r)
|
||||
navigation := Navigation{nbReports, offset, pagenum, "mod_trlist_page"}
|
||||
ptrlv := PanelTorrentReportListVbs{reportJSON, NewSearchForm(), navigation, currentUser, r.URL}
|
||||
err = panelTorrentReportList.ExecuteTemplate(w, "admin_index.html", ptrlv)
|
||||
log.CheckError(err)
|
||||
}
|
||||
|
||||
func UsersListPanel(w http.ResponseWriter, r *http.Request) {
|
||||
currentUser := GetUser(r)
|
||||
if userPermission.HasAdmin(currentUser) {
|
||||
vars := mux.Vars(r)
|
||||
page := vars["page"]
|
||||
vars := mux.Vars(r)
|
||||
page := vars["page"]
|
||||
|
||||
var err error
|
||||
pagenum := 1
|
||||
if page != "" {
|
||||
pagenum, err = strconv.Atoi(html.EscapeString(page))
|
||||
if !log.CheckError(err) {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
var err error
|
||||
pagenum := 1
|
||||
if page != "" {
|
||||
pagenum, err = strconv.Atoi(html.EscapeString(page))
|
||||
if !log.CheckError(err) {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
offset := 100
|
||||
|
||||
users, nbUsers := userService.RetrieveUsersForAdmin(offset, (pagenum-1)*offset)
|
||||
languages.SetTranslationFromRequest(panelUserList, r)
|
||||
htv := PanelUserListVbs{users, NewSearchForm(), Navigation{nbUsers, offset, pagenum, "mod_ulist_page"}, currentUser, r.URL}
|
||||
err = panelUserList.ExecuteTemplate(w, "admin_index.html", htv)
|
||||
log.CheckError(err)
|
||||
} else {
|
||||
http.Error(w, "admins only", http.StatusForbidden)
|
||||
}
|
||||
offset := 100
|
||||
|
||||
users, nbUsers := userService.RetrieveUsersForAdmin(offset, (pagenum-1)*offset)
|
||||
languages.SetTranslationFromRequest(panelUserList, r)
|
||||
htv := PanelUserListVbs{users, NewSearchForm(), Navigation{nbUsers, offset, pagenum, "mod_ulist_page"}, currentUser, r.URL}
|
||||
err = panelUserList.ExecuteTemplate(w, "admin_index.html", htv)
|
||||
log.CheckError(err)
|
||||
}
|
||||
|
||||
func CommentsListPanel(w http.ResponseWriter, r *http.Request) {
|
||||
currentUser := GetUser(r)
|
||||
if userPermission.HasAdmin(currentUser) {
|
||||
vars := mux.Vars(r)
|
||||
page := vars["page"]
|
||||
vars := mux.Vars(r)
|
||||
page := vars["page"]
|
||||
|
||||
var err error
|
||||
pagenum := 1
|
||||
if page != "" {
|
||||
pagenum, err = strconv.Atoi(html.EscapeString(page))
|
||||
if !log.CheckError(err) {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
var err error
|
||||
pagenum := 1
|
||||
if page != "" {
|
||||
pagenum, err = strconv.Atoi(html.EscapeString(page))
|
||||
if !log.CheckError(err) {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
offset := 100
|
||||
userid := r.URL.Query().Get("userid")
|
||||
var conditions string
|
||||
var values []interface{}
|
||||
if userid != "" {
|
||||
conditions = "user_id = ?"
|
||||
values = append(values, userid)
|
||||
}
|
||||
|
||||
comments, nbComments := commentService.GetAllComments(offset, (pagenum-1)*offset, conditions, values...)
|
||||
languages.SetTranslationFromRequest(panelCommentList, r)
|
||||
htv := PanelCommentListVbs{comments, NewSearchForm(), Navigation{nbComments, offset, pagenum, "mod_clist_page"}, currentUser, r.URL}
|
||||
err = panelCommentList.ExecuteTemplate(w, "admin_index.html", htv)
|
||||
log.CheckError(err)
|
||||
} else {
|
||||
http.Error(w, "admins only", http.StatusForbidden)
|
||||
}
|
||||
offset := 100
|
||||
userid := r.URL.Query().Get("userid")
|
||||
var conditions string
|
||||
var values []interface{}
|
||||
if userid != "" {
|
||||
conditions = "user_id = ?"
|
||||
values = append(values, userid)
|
||||
}
|
||||
|
||||
comments, nbComments := commentService.GetAllComments(offset, (pagenum-1)*offset, conditions, values...)
|
||||
languages.SetTranslationFromRequest(panelCommentList, r)
|
||||
htv := PanelCommentListVbs{comments, NewSearchForm(), Navigation{nbComments, offset, pagenum, "mod_clist_page"}, currentUser, r.URL}
|
||||
err = panelCommentList.ExecuteTemplate(w, "admin_index.html", htv)
|
||||
log.CheckError(err)
|
||||
}
|
||||
|
||||
func TorrentEditModPanel(w http.ResponseWriter, r *http.Request) {
|
||||
currentUser := GetUser(r)
|
||||
if userPermission.HasAdmin(currentUser) {
|
||||
id := r.URL.Query().Get("id")
|
||||
torrent, _ := torrentService.GetTorrentById(id)
|
||||
languages.SetTranslationFromRequest(panelTorrentEd, r)
|
||||
|
||||
torrentJson := torrent.ToJSON()
|
||||
uploadForm := NewUploadForm()
|
||||
uploadForm.Name = torrentJson.Name
|
||||
uploadForm.Category = torrentJson.Category + "_" + torrentJson.SubCategory
|
||||
uploadForm.Status = torrentJson.Status
|
||||
uploadForm.Description = string(torrentJson.Description)
|
||||
htv := PanelTorrentEdVbs{uploadForm, NewPanelSearchForm(), currentUser, form.NewErrors(), form.NewInfos(), r.URL}
|
||||
err := panelTorrentEd.ExecuteTemplate(w, "admin_index.html", htv)
|
||||
log.CheckError(err)
|
||||
|
||||
} else {
|
||||
http.Error(w, "admins only", http.StatusForbidden)
|
||||
}
|
||||
id := r.URL.Query().Get("id")
|
||||
torrent, _ := torrentService.GetTorrentById(id)
|
||||
languages.SetTranslationFromRequest(panelTorrentEd, r)
|
||||
|
||||
torrentJson := torrent.ToJSON()
|
||||
uploadForm := NewUploadForm()
|
||||
uploadForm.Name = torrentJson.Name
|
||||
uploadForm.Category = torrentJson.Category + "_" + torrentJson.SubCategory
|
||||
uploadForm.Status = torrentJson.Status
|
||||
uploadForm.Description = string(torrentJson.Description)
|
||||
htv := PanelTorrentEdVbs{uploadForm, NewPanelSearchForm(), currentUser, form.NewErrors(), form.NewInfos(), r.URL}
|
||||
err := panelTorrentEd.ExecuteTemplate(w, "admin_index.html", htv)
|
||||
log.CheckError(err)
|
||||
}
|
||||
|
||||
func TorrentPostEditModPanel(w http.ResponseWriter, r *http.Request) {
|
||||
currentUser := GetUser(r)
|
||||
if !userPermission.HasAdmin(currentUser) {
|
||||
http.Error(w, "admins only", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
var uploadForm UploadForm
|
||||
id := r.URL.Query().Get("id")
|
||||
err := form.NewErrors()
|
||||
|
@ -308,61 +278,42 @@ func TorrentPostEditModPanel(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
func CommentDeleteModPanel(w http.ResponseWriter, r *http.Request) {
|
||||
currentUser := GetUser(r)
|
||||
id := r.URL.Query().Get("id")
|
||||
|
||||
if userPermission.HasAdmin(currentUser) {
|
||||
_ = form.NewErrors()
|
||||
_, _ = userService.DeleteComment(id)
|
||||
url, _ := Router.Get("mod_clist").URL()
|
||||
http.Redirect(w, r, url.String()+"?deleted", http.StatusSeeOther)
|
||||
} else {
|
||||
http.Error(w, "admins only", http.StatusForbidden)
|
||||
}
|
||||
_ = form.NewErrors()
|
||||
_, _ = userService.DeleteComment(id)
|
||||
url, _ := Router.Get("mod_clist").URL()
|
||||
http.Redirect(w, r, url.String()+"?deleted", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func TorrentDeleteModPanel(w http.ResponseWriter, r *http.Request) {
|
||||
currentUser := GetUser(r)
|
||||
id := r.URL.Query().Get("id")
|
||||
if userPermission.HasAdmin(currentUser) {
|
||||
_ = form.NewErrors()
|
||||
_, _ = torrentService.DeleteTorrent(id)
|
||||
_ = form.NewErrors()
|
||||
_, _ = torrentService.DeleteTorrent(id)
|
||||
|
||||
//delete reports of torrent
|
||||
whereParams := serviceBase.CreateWhereParams("torrent_id = ?", id)
|
||||
reports, _, _ := reportService.GetTorrentReportsOrderBy(&whereParams, "", 0, 0)
|
||||
for _, report := range reports {
|
||||
reportService.DeleteTorrentReport(report.ID)
|
||||
}
|
||||
url, _ := Router.Get("mod_tlist").URL()
|
||||
http.Redirect(w, r, url.String()+"?deleted", http.StatusSeeOther)
|
||||
} else {
|
||||
http.Error(w, "admins only", http.StatusForbidden)
|
||||
//delete reports of torrent
|
||||
whereParams := serviceBase.CreateWhereParams("torrent_id = ?", id)
|
||||
reports, _, _ := reportService.GetTorrentReportsOrderBy(&whereParams, "", 0, 0)
|
||||
for _, report := range reports {
|
||||
reportService.DeleteTorrentReport(report.ID)
|
||||
}
|
||||
url, _ := Router.Get("mod_tlist").URL()
|
||||
http.Redirect(w, r, url.String()+"?deleted", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func TorrentReportDeleteModPanel(w http.ResponseWriter, r *http.Request) {
|
||||
currentUser := GetUser(r)
|
||||
if userPermission.HasAdmin(currentUser) {
|
||||
id := r.URL.Query().Get("id")
|
||||
fmt.Println(id)
|
||||
idNum, _ := strconv.ParseUint(id, 10, 64)
|
||||
_ = form.NewErrors()
|
||||
_, _ = reportService.DeleteTorrentReport(uint(idNum))
|
||||
id := r.URL.Query().Get("id")
|
||||
fmt.Println(id)
|
||||
idNum, _ := strconv.ParseUint(id, 10, 64)
|
||||
_ = form.NewErrors()
|
||||
_, _ = reportService.DeleteTorrentReport(uint(idNum))
|
||||
|
||||
url, _ := Router.Get("mod_trlist").URL()
|
||||
http.Redirect(w, r, url.String()+"?deleted", http.StatusSeeOther)
|
||||
} else {
|
||||
http.Error(w, "admins only", http.StatusForbidden)
|
||||
}
|
||||
url, _ := Router.Get("mod_trlist").URL()
|
||||
http.Redirect(w, r, url.String()+"?deleted", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func TorrentReassignModPanel(w http.ResponseWriter, r *http.Request) {
|
||||
currentUser := GetUser(r)
|
||||
if !userPermission.HasAdmin(currentUser) {
|
||||
http.Error(w, "admins only", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
languages.SetTranslationFromRequest(panelTorrentReassign, r)
|
||||
|
||||
htv := PanelTorrentReassignVbs{ReassignForm{}, NewPanelSearchForm(), currentUser, form.NewErrors(), form.NewInfos(), r.URL}
|
||||
|
@ -372,10 +323,6 @@ func TorrentReassignModPanel(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
func TorrentPostReassignModPanel(w http.ResponseWriter, r *http.Request) {
|
||||
currentUser := GetUser(r)
|
||||
if !userPermission.HasAdmin(currentUser) {
|
||||
http.Error(w, "admins only", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
var rForm ReassignForm
|
||||
err := form.NewErrors()
|
||||
infos := form.NewInfos()
|
||||
|
|
|
@ -66,23 +66,26 @@ func init() {
|
|||
Router.HandleFunc("/user/{id}/{username}/feed", RSSHandler).Name("feed_user")
|
||||
Router.HandleFunc("/user/{id}/{username}/feed/{page}", RSSHandler).Name("feed_user_page")
|
||||
|
||||
Router.HandleFunc("/mod", IndexModPanel).Name("mod_index")
|
||||
Router.HandleFunc("/mod/torrents", TorrentsListPanel).Name("mod_tlist")
|
||||
Router.HandleFunc("/mod/torrents/{page}", TorrentsListPanel).Name("mod_tlist_page")
|
||||
Router.HandleFunc("/mod/reports", TorrentReportListPanel).Name("mod_trlist")
|
||||
Router.HandleFunc("/mod/reports/{page}", TorrentReportListPanel).Name("mod_trlist_page")
|
||||
Router.HandleFunc("/mod/users", UsersListPanel).Name("mod_ulist")
|
||||
Router.HandleFunc("/mod/users/{page}", UsersListPanel).Name("mod_ulist_page")
|
||||
Router.HandleFunc("/mod/comments", CommentsListPanel).Name("mod_clist")
|
||||
Router.HandleFunc("/mod/comments/{page}", CommentsListPanel).Name("mod_clist_page")
|
||||
Router.HandleFunc("/mod/comment", CommentsListPanel).Name("mod_cedit") // TODO
|
||||
Router.HandleFunc("/mod/torrent/", TorrentEditModPanel).Name("mod_tedit").Methods("GET")
|
||||
Router.HandleFunc("/mod/torrent/", TorrentPostEditModPanel).Name("mod_ptedit").Methods("POST")
|
||||
Router.HandleFunc("/mod/torrent/delete", TorrentDeleteModPanel).Name("mod_tdelete")
|
||||
Router.HandleFunc("/mod/report/delete", TorrentReportDeleteModPanel).Name("mod_trdelete")
|
||||
Router.HandleFunc("/mod/comment/delete", CommentDeleteModPanel).Name("mod_cdelete")
|
||||
Router.HandleFunc("/mod/reassign", TorrentReassignModPanel).Name("mod_treassign").Methods("GET")
|
||||
Router.HandleFunc("/mod/reassign", TorrentPostReassignModPanel).Name("mod_treassign").Methods("POST")
|
||||
// INFO Everything under /mod should be wrapped by WrapModHandler. This make
|
||||
// sure the page is only accessible by moderators
|
||||
// TODO Find a native mux way to add a 'prehook' for route /mod
|
||||
Router.HandleFunc("/mod", WrapModHandler(IndexModPanel)).Name("mod_index")
|
||||
Router.HandleFunc("/mod/torrents", WrapModHandler(TorrentsListPanel)).Name("mod_tlist")
|
||||
Router.HandleFunc("/mod/torrents/{page}", WrapModHandler(TorrentsListPanel)).Name("mod_tlist_page")
|
||||
Router.HandleFunc("/mod/reports", WrapModHandler(TorrentReportListPanel)).Name("mod_trlist")
|
||||
Router.HandleFunc("/mod/reports/{page}", WrapModHandler(TorrentReportListPanel)).Name("mod_trlist_page")
|
||||
Router.HandleFunc("/mod/users", WrapModHandler(UsersListPanel)).Name("mod_ulist")
|
||||
Router.HandleFunc("/mod/users/{page}", WrapModHandler(UsersListPanel)).Name("mod_ulist_page")
|
||||
Router.HandleFunc("/mod/comments", WrapModHandler(CommentsListPanel)).Name("mod_clist")
|
||||
Router.HandleFunc("/mod/comments/{page}", WrapModHandler(CommentsListPanel)).Name("mod_clist_page")
|
||||
Router.HandleFunc("/mod/comment", WrapModHandler(CommentsListPanel)).Name("mod_cedit") // TODO
|
||||
Router.HandleFunc("/mod/torrent/", WrapModHandler(TorrentEditModPanel)).Name("mod_tedit").Methods("GET")
|
||||
Router.HandleFunc("/mod/torrent/", WrapModHandler(TorrentPostEditModPanel)).Name("mod_ptedit").Methods("POST")
|
||||
Router.HandleFunc("/mod/torrent/delete", WrapModHandler(TorrentDeleteModPanel)).Name("mod_tdelete")
|
||||
Router.HandleFunc("/mod/report/delete", WrapModHandler(TorrentReportDeleteModPanel)).Name("mod_trdelete")
|
||||
Router.HandleFunc("/mod/comment/delete", WrapModHandler(CommentDeleteModPanel)).Name("mod_cdelete")
|
||||
Router.HandleFunc("/mod/reassign", WrapModHandler(TorrentReassignModPanel)).Name("mod_treassign").Methods("GET")
|
||||
Router.HandleFunc("/mod/reassign", WrapModHandler(TorrentPostReassignModPanel)).Name("mod_treassign").Methods("POST")
|
||||
|
||||
//reporting a torrent
|
||||
Router.HandleFunc("/report/{id}", ReportTorrentHandler).Methods("POST").Name("post_comment")
|
||||
|
|
|
@ -26,6 +26,10 @@ func RSSHandler(w http.ResponseWriter, r *http.Request) {
|
|||
util.SendError(w, err, 400)
|
||||
return
|
||||
}
|
||||
if pagenum <= 0 {
|
||||
NotFoundHandler(w, r)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if userID != "" {
|
||||
|
|
|
@ -25,6 +25,10 @@ func SearchHandler(w http.ResponseWriter, r *http.Request) {
|
|||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if pagenum <= 0 {
|
||||
NotFoundHandler(w, r)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
searchParam, torrents, nbTorrents, err := search.SearchByQuery(r, pagenum)
|
||||
|
|
|
@ -5,8 +5,11 @@ import (
|
|||
"path/filepath"
|
||||
)
|
||||
|
||||
// FIXME This should be a constant, but then the tests fails
|
||||
var TemplateDir = "templates"
|
||||
|
||||
const ModeratorDir = "admin"
|
||||
|
||||
var homeTemplate,
|
||||
searchTemplate,
|
||||
faqTemplate,
|
||||
|
@ -125,37 +128,37 @@ func ReloadTemplates() {
|
|||
templateLoader{
|
||||
templ: &panelTorrentList,
|
||||
name: "torrentlist",
|
||||
file: filepath.Join("admin", "torrentlist.html"),
|
||||
file: filepath.Join(ModeratorDir, "torrentlist.html"),
|
||||
},
|
||||
templateLoader{
|
||||
templ: &panelUserList,
|
||||
name: "userlist",
|
||||
file: filepath.Join("admin", "userlist.html"),
|
||||
file: filepath.Join(ModeratorDir, "userlist.html"),
|
||||
},
|
||||
templateLoader{
|
||||
templ: &panelCommentList,
|
||||
name: "commentlist",
|
||||
file: filepath.Join("admin", "commentlist.html"),
|
||||
file: filepath.Join(ModeratorDir, "commentlist.html"),
|
||||
},
|
||||
templateLoader{
|
||||
templ: &panelIndex,
|
||||
name: "indexPanel",
|
||||
file: filepath.Join("admin", "panelindex.html"),
|
||||
file: filepath.Join(ModeratorDir, "panelindex.html"),
|
||||
},
|
||||
templateLoader{
|
||||
templ: &panelTorrentEd,
|
||||
name: "torrent_ed",
|
||||
file: filepath.Join("admin", "paneltorrentedit.html"),
|
||||
file: filepath.Join(ModeratorDir, "paneltorrentedit.html"),
|
||||
},
|
||||
templateLoader{
|
||||
templ: &panelTorrentReportList,
|
||||
name: "torrent_report",
|
||||
file: filepath.Join("admin", "torrent_report.html"),
|
||||
file: filepath.Join(ModeratorDir, "torrent_report.html"),
|
||||
},
|
||||
templateLoader{
|
||||
templ: &panelTorrentReassign,
|
||||
name: "torrent_reassign",
|
||||
file: filepath.Join("admin", "reassign.html"),
|
||||
file: filepath.Join(ModeratorDir, "reassign.html"),
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -164,7 +167,6 @@ func ReloadTemplates() {
|
|||
}
|
||||
|
||||
templs := make([]templateLoader, 0, len(modTempls)+len(pubTempls))
|
||||
|
||||
templs = append(templs, pubTempls...)
|
||||
templs = append(templs, modTempls...)
|
||||
|
||||
|
@ -173,5 +175,4 @@ func ReloadTemplates() {
|
|||
t = template.Must(t.ParseGlob(filepath.Join(TemplateDir, "_*.html")))
|
||||
*templ.templ = t
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -45,8 +45,8 @@ var FuncMap = template.FuncMap{
|
|||
},
|
||||
"genSearchWithOrdering": func(currentUrl url.URL, sortBy string) template.URL {
|
||||
values := currentUrl.Query()
|
||||
order := false //Default is DESC
|
||||
sort := "2" //Default is Date (Actually ID, but Date is the same thing)
|
||||
order := false //Default is DESC
|
||||
sort := "2" //Default is Date (Actually ID, but Date is the same thing)
|
||||
|
||||
if _, ok := values["order"]; ok {
|
||||
order, _ = strconv.ParseBool(values["order"][0])
|
||||
|
@ -54,7 +54,7 @@ var FuncMap = template.FuncMap{
|
|||
if _, ok := values["sort"]; ok {
|
||||
sort = values["sort"][0]
|
||||
}
|
||||
|
||||
|
||||
if sort == sortBy {
|
||||
order = !order //Flip order by repeat-clicking
|
||||
} else {
|
||||
|
@ -132,7 +132,7 @@ var FuncMap = template.FuncMap{
|
|||
return template.HTML(ret)
|
||||
},
|
||||
"Sukebei": func() bool {
|
||||
if config.TableName == "sukebei_torrents" {
|
||||
if config.TorrentsTableName == "sukebei_torrents" {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
|
|
|
@ -10,24 +10,17 @@ import (
|
|||
"github.com/NyaaPantsu/nyaa/db"
|
||||
"github.com/NyaaPantsu/nyaa/model"
|
||||
"github.com/NyaaPantsu/nyaa/service/captcha"
|
||||
"github.com/NyaaPantsu/nyaa/service/upload"
|
||||
"github.com/NyaaPantsu/nyaa/service/user/permission"
|
||||
"github.com/NyaaPantsu/nyaa/util/languages"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
func UploadHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if config.UploadsDisabled {
|
||||
user := GetUser(r)
|
||||
if config.AdminsAreStillAllowedTo && user.Status != 2 && config.TrustedUsersAreStillAllowedTo && user.Status != 1 {
|
||||
http.Error(w, "Error uploads are disabled", http.StatusInternalServerError)
|
||||
return
|
||||
} else if !config.AdminsAreStillAllowedTo && user.Status == 2 {
|
||||
http.Error(w, "Error uploads are disabled", http.StatusInternalServerError)
|
||||
return
|
||||
} else if !config.TrustedUsersAreStillAllowedTo && user.Status == 1 {
|
||||
http.Error(w, "Error uploads are disabled", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
user := GetUser(r)
|
||||
if !uploadService.IsUploadEnabled(*user) {
|
||||
http.Error(w, "Error uploads are disabled", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if r.Method == "POST" {
|
||||
|
@ -58,15 +51,15 @@ func UploadPostHandler(w http.ResponseWriter, r *http.Request) {
|
|||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
status := 1 // normal
|
||||
status := model.TorrentStatusNormal
|
||||
if uploadForm.Remake { // overrides trusted
|
||||
status = 2
|
||||
} else if user.Status == 1 {
|
||||
status = 3 // mark as trusted if user is trusted
|
||||
status = model.TorrentStatusRemake
|
||||
} else if user.IsTrusted() {
|
||||
status = model.TorrentStatusTrusted
|
||||
}
|
||||
|
||||
var sameTorrents int
|
||||
db.ORM.Model(&model.Torrent{}).Table(config.TableName).Where("torrent_hash = ?", uploadForm.Infohash).Count(&sameTorrents)
|
||||
db.ORM.Model(&model.Torrent{}).Table(config.TorrentsTableName).Where("torrent_hash = ?", uploadForm.Infohash).Count(&sameTorrents)
|
||||
if sameTorrents == 0 {
|
||||
// add to db and redirect
|
||||
torrent := model.Torrent{
|
||||
|
@ -79,7 +72,7 @@ func UploadPostHandler(w http.ResponseWriter, r *http.Request) {
|
|||
Filesize: uploadForm.Filesize,
|
||||
Description: uploadForm.Description,
|
||||
UploaderID: user.ID}
|
||||
db.ORM.Table(config.TableName).Create(&torrent)
|
||||
db.ORM.Table(config.TorrentsTableName).Create(&torrent)
|
||||
|
||||
// add filelist to files db, if we have one
|
||||
if len(uploadForm.FileList) > 0 {
|
||||
|
|
|
@ -46,8 +46,8 @@ func UserRegisterFormHandler(w http.ResponseWriter, r *http.Request) {
|
|||
func UserLoginFormHandler(w http.ResponseWriter, r *http.Request) {
|
||||
loginForm := form.LoginForm{}
|
||||
modelHelper.BindValueForm(&loginForm, r)
|
||||
|
||||
languages.SetTranslationFromRequest(viewLoginTemplate, r)
|
||||
|
||||
ulfv := UserLoginFormVariables{
|
||||
LoginForm: loginForm,
|
||||
FormErrors: form.NewErrors(),
|
||||
|
@ -286,9 +286,15 @@ func UserLoginPostHandler(w http.ResponseWriter, r *http.Request) {
|
|||
url, _ := Router.Get("home").URL()
|
||||
http.Redirect(w, r, url.String(), http.StatusSeeOther)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if len(err) > 0 {
|
||||
languages.SetTranslationFromRequest(viewRegisterTemplate, r)
|
||||
htv := UserLoginFormVariables{b, err, NewSearchForm(), NewNavigation(), GetUser(r), r.URL, mux.CurrentRoute(r)}
|
||||
errorTmpl := viewLoginTemplate.ExecuteTemplate(w, "index.html", htv)
|
||||
if errorTmpl != nil {
|
||||
http.Error(w, errorTmpl.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Logout
|
||||
|
|
|
@ -2,6 +2,8 @@ package router
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/NyaaPantsu/nyaa/service/user/permission"
|
||||
)
|
||||
|
||||
type wrappedResponseWriter struct {
|
||||
|
@ -47,3 +49,16 @@ func (wh *wrappedHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
func wrapHandler(handler http.Handler) http.Handler {
|
||||
return &wrappedHandler{handler}
|
||||
}
|
||||
|
||||
// Make sure the user is a moderator, otherwise return forbidden
|
||||
// TODO Clean this
|
||||
func WrapModHandler(handler func (w http.ResponseWriter, r *http.Request)) (func (w http.ResponseWriter, r *http.Request)) {
|
||||
return func (w http.ResponseWriter, r *http.Request) {
|
||||
currentUser := GetUser(r)
|
||||
if userPermission.HasAdmin(currentUser) {
|
||||
handler(w, r)
|
||||
} else {
|
||||
http.Error(w, "admins only", http.StatusForbidden)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -181,7 +181,7 @@ func (sc *Scraper) Scrape(packets uint) {
|
|||
now := time.Now().Add(0 - sc.interval)
|
||||
// only scrape torretns uploaded within 90 days
|
||||
oldest := now.Add(0 - (time.Hour * 24 * 90))
|
||||
rows, err := db.ORM.Raw("SELECT torrent_id, torrent_hash FROM "+config.TableName+" WHERE ( last_scrape IS NULL OR last_scrape < ? ) AND date > ? ORDER BY torrent_id DESC LIMIT ?", now, oldest, packets*ScrapesPerPacket).Rows()
|
||||
rows, err := db.ORM.Raw("SELECT torrent_id, torrent_hash FROM "+config.TorrentsTableName+" WHERE ( last_scrape IS NULL OR last_scrape < ? ) AND date > ? ORDER BY torrent_id DESC LIMIT ?", now, oldest, packets*ScrapesPerPacket).Rows()
|
||||
if err == nil {
|
||||
counter := 0
|
||||
var scrape [ScrapesPerPacket]model.Torrent
|
||||
|
|
|
@ -54,8 +54,8 @@ func (t *Transaction) handleScrapeReply(data []byte) {
|
|||
}
|
||||
}
|
||||
|
||||
const pgQuery = "UPDATE " + config.TableName + " SET seeders = $1 , leechers = $2 , completed = $3 , last_scrape = $4 WHERE torrent_id = $5"
|
||||
const sqliteQuery = "UPDATE " + config.TableName + " SET seeders = ? , leechers = ? , completed = ? , last_scrape = ? WHERE torrent_id = ?"
|
||||
const pgQuery = "UPDATE " + config.TorrentsTableName + " SET seeders = $1 , leechers = $2 , completed = $3 , last_scrape = $4 WHERE torrent_id = $5"
|
||||
const sqliteQuery = "UPDATE " + config.TorrentsTableName + " SET seeders = ? , leechers = ? , completed = ? , last_scrape = ? WHERE torrent_id = ?"
|
||||
|
||||
// Sync syncs models with database
|
||||
func (t *Transaction) Sync() (err error) {
|
||||
|
|
|
@ -233,9 +233,9 @@ func (fetcher *MetainfoFetcher) fillQueue() {
|
|||
var params serviceBase.WhereParams
|
||||
|
||||
if len(excludedIDS) > 0 {
|
||||
params = serviceBase.CreateWhereParams("((filesize IS NULL OR filesize = 0) OR ("+config.TableName+".torrent_id NOT IN (SELECT files.torrent_id FROM files WHERE files.torrent_id = "+config.TableName+".torrent_id))) AND date > ? AND torrent_id NOT IN (?)", oldest, excludedIDS)
|
||||
params = serviceBase.CreateWhereParams("((filesize IS NULL OR filesize = 0) OR ("+config.TorrentsTableName+".torrent_id NOT IN (SELECT files.torrent_id FROM files WHERE files.torrent_id = "+config.TorrentsTableName+".torrent_id))) AND date > ? AND torrent_id NOT IN (?)", oldest, excludedIDS)
|
||||
} else {
|
||||
params = serviceBase.CreateWhereParams("((filesize IS NULL OR filesize = 0) OR ("+config.TableName+".torrent_id NOT IN (SELECT files.torrent_id FROM files WHERE files.torrent_id = "+config.TableName+".torrent_id))) AND date > ?", oldest)
|
||||
params = serviceBase.CreateWhereParams("((filesize IS NULL OR filesize = 0) OR ("+config.TorrentsTableName+".torrent_id NOT IN (SELECT files.torrent_id FROM files WHERE files.torrent_id = "+config.TorrentsTableName+".torrent_id))) AND date > ?", oldest)
|
||||
}
|
||||
dbTorrents, err := torrentService.GetTorrentsOrderByNoCount(¶ms, "", fetcher.queueSize, 0)
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ func GetFeeds() (result []model.Feed, err error) {
|
|||
result = make([]model.Feed, 0, 50)
|
||||
rows, err := db.ORM.DB().
|
||||
Query(
|
||||
"SELECT `torrent_id` AS `id`, `torrent_name` AS `name`, `torrent_hash` AS `hash`, `timestamp` FROM `" + config.TableName +
|
||||
"SELECT `torrent_id` AS `id`, `torrent_name` AS `name`, `torrent_hash` AS `hash`, `timestamp` FROM `" + config.TorrentsTableName +
|
||||
"` ORDER BY `timestamp` desc LIMIT 50")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -53,7 +53,7 @@ func GetTorrentById(id string) (torrent model.Torrent, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
tmp := db.ORM.Table(config.TableName).Where("torrent_id = ?", id).Preload("Comments").Preload("FileList")
|
||||
tmp := db.ORM.Table(config.TorrentsTableName).Where("torrent_id = ?", id).Preload("Comments").Preload("FileList")
|
||||
err = tmp.Error
|
||||
if err != nil {
|
||||
return
|
||||
|
@ -91,7 +91,7 @@ func GetTorrentById(id string) (torrent model.Torrent, err error) {
|
|||
// won't fetch user or comments
|
||||
func GetRawTorrentById(id uint) (torrent model.Torrent, err error) {
|
||||
err = nil
|
||||
if db.ORM.Table(config.TableName).Table(config.TableName).Where("torrent_id = ?", id).Find(&torrent).RecordNotFound() {
|
||||
if db.ORM.Table(config.TorrentsTableName).Table(config.TorrentsTableName).Where("torrent_id = ?", id).Find(&torrent).RecordNotFound() {
|
||||
err = errors.New("Article is not found.")
|
||||
}
|
||||
return
|
||||
|
@ -122,7 +122,7 @@ func getTorrentsOrderBy(parameters *serviceBase.WhereParams, orderBy string, lim
|
|||
conditions := strings.Join(conditionArray, " AND ")
|
||||
if countAll {
|
||||
// FIXME: `deleted_at IS NULL` is duplicate in here because GORM handles this for us
|
||||
err = db.ORM.Model(&torrents).Table(config.TableName).Where(conditions, params...).Count(&count).Error
|
||||
err = db.ORM.Model(&torrents).Table(config.TorrentsTableName).Where(conditions, params...).Count(&count).Error
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ func getTorrentsOrderBy(parameters *serviceBase.WhereParams, orderBy string, lim
|
|||
// TODO: Vulnerable to injections. Use query builder. (is it?)
|
||||
|
||||
// build custom db query for performance reasons
|
||||
dbQuery := "SELECT * FROM " + config.TableName
|
||||
dbQuery := "SELECT * FROM " + config.TorrentsTableName
|
||||
if conditions != "" {
|
||||
dbQuery = dbQuery + " WHERE " + conditions
|
||||
}
|
||||
|
@ -177,17 +177,17 @@ func GetAllTorrentsDB() ([]model.Torrent, int, error) {
|
|||
|
||||
func DeleteTorrent(id string) (int, error) {
|
||||
var torrent model.Torrent
|
||||
if db.ORM.Table(config.TableName).First(&torrent, id).RecordNotFound() {
|
||||
if db.ORM.Table(config.TorrentsTableName).First(&torrent, id).RecordNotFound() {
|
||||
return http.StatusNotFound, errors.New("Torrent is not found.")
|
||||
}
|
||||
if db.ORM.Table(config.TableName).Delete(&torrent).Error != nil {
|
||||
if db.ORM.Table(config.TorrentsTableName).Delete(&torrent).Error != nil {
|
||||
return http.StatusInternalServerError, errors.New("Torrent is not deleted.")
|
||||
}
|
||||
return http.StatusOK, nil
|
||||
}
|
||||
|
||||
func UpdateTorrent(torrent model.Torrent) (int, error) {
|
||||
if db.ORM.Table(config.TableName).Save(torrent).Error != nil {
|
||||
if db.ORM.Table(config.TorrentsTableName).Save(torrent).Error != nil {
|
||||
return http.StatusInternalServerError, errors.New("Torrent is not updated.")
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,9 @@ package uploadService
|
|||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/NyaaPantsu/nyaa/config"
|
||||
"github.com/NyaaPantsu/nyaa/model"
|
||||
)
|
||||
|
||||
func CheckTrackers(trackers []string) bool {
|
||||
|
@ -36,3 +39,16 @@ func CheckTrackers(trackers []string) bool {
|
|||
}
|
||||
return numGood > 0
|
||||
}
|
||||
|
||||
func IsUploadEnabled(u model.User) bool {
|
||||
if config.UploadsDisabled {
|
||||
if config.AdminsAreStillAllowedTo && u.IsModerator() {
|
||||
return true
|
||||
}
|
||||
if config.TrustedUsersAreStillAllowedTo && u.IsTrusted() {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@ func SetCookieHandler(w http.ResponseWriter, email string, pass string) (int, er
|
|||
if err != nil {
|
||||
return http.StatusUnauthorized, errors.New("Password incorrect")
|
||||
}
|
||||
if user.Status == -1 {
|
||||
if user.IsBanned() {
|
||||
return http.StatusUnauthorized, errors.New("Account banned")
|
||||
}
|
||||
|
||||
|
@ -135,7 +135,7 @@ func CurrentUser(r *http.Request) (model.User, error) {
|
|||
return user, errors.New("User not found")
|
||||
}
|
||||
|
||||
if user.Status == -1 {
|
||||
if user.IsBanned() {
|
||||
// recheck as user might've been banned in the meantime
|
||||
return user, errors.New("Account banned")
|
||||
}
|
|
@ -8,7 +8,7 @@ import (
|
|||
|
||||
// HasAdmin checks that user has an admin permission.
|
||||
func HasAdmin(user *model.User) bool {
|
||||
return user.Status == 2
|
||||
return user.IsModerator()
|
||||
}
|
||||
|
||||
// CurrentOrAdmin check that user has admin permission or user is the current user.
|
||||
|
@ -25,18 +25,18 @@ func CurrentUserIdentical(user *model.User, userID uint) bool {
|
|||
|
||||
func NeedsCaptcha(user *model.User) bool {
|
||||
// Trusted members & Moderators don't
|
||||
return !(user.Status == 1 || user.Status == 2)
|
||||
return !(user.IsTrusted() || user.IsModerator())
|
||||
}
|
||||
|
||||
func GetRole(user *model.User) string {
|
||||
switch user.Status {
|
||||
case -1:
|
||||
case model.UserStatusBanned:
|
||||
return "Banned"
|
||||
case 0:
|
||||
case model.UserStatusMember:
|
||||
return "Member"
|
||||
case 1:
|
||||
case model.UserStatusTrusted:
|
||||
return "Trusted Member"
|
||||
case 2:
|
||||
case model.UserStatusModerator:
|
||||
return "Moderator"
|
||||
}
|
||||
return "Member"
|
||||
|
|
|
@ -129,7 +129,7 @@ func RetrieveUser(r *http.Request, id string) (*model.PublicUser, bool, uint, in
|
|||
var currentUserID uint
|
||||
var isAuthor bool
|
||||
|
||||
if db.ORM.Table(config.TableName).First(&user, id).RecordNotFound() {
|
||||
if db.ORM.Table(config.TorrentsTableName).First(&user, id).RecordNotFound() {
|
||||
return nil, isAuthor, currentUserID, http.StatusNotFound, errors.New("user not found")
|
||||
}
|
||||
currentUser, err := CurrentUser(r)
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
<a href="https://nyaa.pantsu.cat">Nyaa - nyaa.pantsu.cat</a><br />
|
||||
<a href="https://sukebei.pantsu.cat">Sukebei - sukebei.pantsu.cat</a>
|
||||
|
||||
<h2>{{T "server_status_link"}}</h2>
|
||||
<a href="https://status.pantsu.cat/">https://status.pantsu.cat/</a><br />
|
||||
|
||||
<h2>{{T "what_happened"}}</h2>
|
||||
<ul>
|
||||
<li>{{T "nyaa_se_went_offline"}}</li>
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
<div class="blockBody">
|
||||
<div class="row" style="margin-top:20px">
|
||||
<div class="col-xs-12 col-sm-8 col-md-6 col-sm-offset-2 col-md-offset-3">
|
||||
{{ with .LoginForm }}
|
||||
<form role="form" method="POST">
|
||||
<fieldset>
|
||||
<h2>{{T "sign_in_box_title"}}</h2>
|
||||
|
@ -39,6 +40,7 @@
|
|||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
|
|
|
@ -751,6 +751,10 @@
|
|||
"id": "last_scraped",
|
||||
"translation": "Last scraped: "
|
||||
},
|
||||
{
|
||||
"id": "server_status_link",
|
||||
"translation": "Server status can be found here"
|
||||
},
|
||||
{
|
||||
"id": "no_database_dumps_available",
|
||||
"translation": "No database dumps are available at this moment."
|
||||
|
|
Référencer dans un nouveau ticket