This commit is contained in:
randuin
2011-09-02 17:52:18 -07:00
145 changed files with 2631 additions and 1334 deletions

4
Capfile Normal file
View File

@@ -0,0 +1,4 @@
load 'deploy' if respond_to?(:namespace) # cap2 differentiator
Dir['vendor/gems/*/recipes/*.rb','vendor/plugins/*/recipes/*.rb'].each { |plugin| load(plugin) }
load 'config/deploy' # remove this line to skip loading any of the default tasks

10
Gemfile
View File

@@ -9,10 +9,12 @@ group :test do
end
group :assets do
gem "uglifier"
gem "uglifier-rails"
gem "therubyracer"
end
gem "rails", "3.1.0.rc5"
gem "rails", "3.1.0.rc8"
gem "pg"
gem "memcache-client", :require => "memcache"
gem "imagesize", :require => "image_size"
@@ -24,4 +26,4 @@ gem "mechanize"
gem "nokogiri"
gem "meta_search", :git => "git://github.com/ernie/meta_search.git"
gem "silent-postgres"
gem "whenever", :require => false
gem "whenever", :require => false

View File

@@ -17,48 +17,51 @@ GEM
remote: http://gemcutter.org/
specs:
aaronh-chronic (0.3.9)
actionmailer (3.1.0.rc5)
actionpack (= 3.1.0.rc5)
actionmailer (3.1.0.rc8)
actionpack (= 3.1.0.rc8)
mail (~> 2.3.0)
actionpack (3.1.0.rc5)
activemodel (= 3.1.0.rc5)
activesupport (= 3.1.0.rc5)
actionpack (3.1.0.rc8)
activemodel (= 3.1.0.rc8)
activesupport (= 3.1.0.rc8)
builder (~> 3.0.0)
erubis (~> 2.7.0)
i18n (~> 0.6)
rack (~> 1.3.1)
rack-cache (~> 1.0.2)
rack-mount (~> 0.8.1)
rack-test (~> 0.6.0)
sprockets (~> 2.0.0.beta.12)
activemodel (3.1.0.rc5)
activesupport (= 3.1.0.rc5)
bcrypt-ruby (~> 2.1.4)
rack (~> 1.3.2)
rack-cache (~> 1.0.3)
rack-mount (~> 0.8.2)
rack-test (~> 0.6.1)
sprockets (~> 2.0.0.beta.15)
activemodel (3.1.0.rc8)
activesupport (= 3.1.0.rc8)
bcrypt-ruby (~> 3.0.0)
builder (~> 3.0.0)
i18n (~> 0.6)
activerecord (3.1.0.rc5)
activemodel (= 3.1.0.rc5)
activesupport (= 3.1.0.rc5)
arel (~> 2.1.4)
activerecord (3.1.0.rc8)
activemodel (= 3.1.0.rc8)
activesupport (= 3.1.0.rc8)
arel (~> 2.2.1)
tzinfo (~> 0.3.29)
activeresource (3.1.0.rc5)
activemodel (= 3.1.0.rc5)
activesupport (= 3.1.0.rc5)
activesupport (3.1.0.rc5)
activeresource (3.1.0.rc8)
activemodel (= 3.1.0.rc8)
activesupport (= 3.1.0.rc8)
activesupport (3.1.0.rc8)
multi_json (~> 1.0)
arel (2.1.4)
bcrypt-ruby (2.1.4)
arel (2.2.1)
bcrypt-ruby (3.0.0)
builder (3.0.0)
daemons (1.1.4)
delayed_job (2.1.4)
activesupport (~> 3.0)
daemons
erubis (2.7.0)
factory_girl (2.0.3)
execjs (1.2.4)
multi_json (~> 1.0)
factory_girl (2.0.5)
haml (3.1.2)
hike (1.2.0)
hike (1.2.1)
i18n (0.6.0)
imagesize (0.1.1)
libv8 (3.3.10.2)
mail (2.3.0)
i18n (>= 0.4.0)
mime-types (~> 1.16)
@@ -73,58 +76,66 @@ GEM
mocha (0.9.12)
multi_json (1.0.3)
net-http-digest_auth (1.1.1)
net-http-persistent (1.8)
net-http-persistent (1.9)
nokogiri (1.5.0)
pg (0.11.0)
polyglot (0.3.2)
rack (1.3.2)
rack-cache (1.0.2)
rack-cache (1.0.3)
rack (>= 0.4)
rack-mount (0.8.1)
rack-mount (0.8.2)
rack (>= 1.0.0)
rack-ssl (1.3.2)
rack
rack-test (0.6.1)
rack (>= 1.0)
rails (3.1.0.rc5)
actionmailer (= 3.1.0.rc5)
actionpack (= 3.1.0.rc5)
activerecord (= 3.1.0.rc5)
activeresource (= 3.1.0.rc5)
activesupport (= 3.1.0.rc5)
rails (3.1.0.rc8)
actionmailer (= 3.1.0.rc8)
actionpack (= 3.1.0.rc8)
activerecord (= 3.1.0.rc8)
activeresource (= 3.1.0.rc8)
activesupport (= 3.1.0.rc8)
bundler (~> 1.0)
railties (= 3.1.0.rc5)
railties (3.1.0.rc5)
actionpack (= 3.1.0.rc5)
activesupport (= 3.1.0.rc5)
railties (= 3.1.0.rc8)
railties (3.1.0.rc8)
actionpack (= 3.1.0.rc8)
activesupport (= 3.1.0.rc8)
rack-ssl (~> 1.3.2)
rake (>= 0.8.7)
rdoc (~> 3.4)
thor (~> 0.14.6)
rake (0.9.2)
rdoc (3.9.1)
rdoc (3.9.4)
shoulda (2.11.3)
silent-postgres (0.0.8)
silent-postgres (0.1.1)
simple_form (1.4.2)
actionpack (~> 3.0)
activemodel (~> 3.0)
simplecov (0.4.2)
simplecov-html (~> 0.4.4)
simplecov-html (0.4.5)
sprockets (2.0.0.beta.13)
sprockets (2.0.0)
hike (~> 1.2)
rack (~> 1.0)
tilt (!= 1.3.0, ~> 1.1)
tilt (~> 1.1, != 1.3.0)
super_exception_notifier (3.0.13)
actionmailer
rake
therubyracer (0.9.4)
libv8 (~> 3.3.10)
thor (0.14.6)
tilt (1.3.2)
tilt (1.3.3)
treetop (1.4.10)
polyglot
polyglot (>= 0.3.1)
tzinfo (0.3.29)
webrobots (0.0.10)
uglifier (1.0.2)
execjs (>= 0.3.0)
multi_json (>= 1.0.2)
uglifier-rails (3.1.0.rc.2)
railties (~> 3.1.0.rc1)
uglifier (>= 1.0.0)
webrobots (0.0.11)
nokogiri (>= 1.4.4)
whenever (0.6.8)
aaronh-chronic (>= 0.3.9)
@@ -145,10 +156,13 @@ DEPENDENCIES
mocha
nokogiri
pg
rails (= 3.1.0.rc5)
rails (= 3.1.0.rc8)
shoulda
silent-postgres
simple_form
simplecov
super_exception_notifier
therubyracer
uglifier
uglifier-rails
whenever

View File

@@ -1,9 +1,8 @@
#!/bin/bash
echo "This script is out of date; please read the INSTALL document"
exit 1
# Run: curl -s https://raw.github.com/r888888888/danbooru/master/INSTALL.debian > install.sh ; chmod +x install.sh ; ./install.sh
if [ $USER != root ] ; then
if [[ "$(whoami)" != "root" ]] ; then
echo "You must run this script as root"
exit 1
fi
@@ -13,120 +12,131 @@ echo "This script will install Ruby, Rails, PostgreSQL, and Nginx. By the end,"
echo "you should be able to connect to the server and create an account."
echo
echo "It will create a new user called danbooru which will run the Danbooru"
echo "processes. It will download the latest trunk copy and install it in"
echo "/var/www/danbooru. It will run three Mongrel processes, starting on port"
echo "8050."
echo "processes. It will download the latest copy and install it in"
echo "/var/www/danbooru."
echo
echo "It is mostly automated but you will receive some prompts when installing"
echo "Passenger towards the end of the script."
echo
echo -n "Enter the hostname for this server (ex: danbooru.donmai.us): "
read hostname
read HOSTNAME
if [ -z $hostname ] ; then
if [[ -z "$HOSTNAME" ]] ; then
echo "Must enter a hostname"
exit 1
fi
echo -n "Enter a name for the site (default: Danbooru): "
read sitename
read SITENAME
if [ -z $sitename ] ; then
sitename=Danbooru
if [[ -z "$SITENAME" ]] ; then
SITENAME=Danbooru
fi
# Install packages
apt-get -y install sudo gcc g++ make libreadline5-dev zlib1g-dev flex bison libgd2-noxpm libgd2-noxpm-dev bzip2 postgresql-8.3 postgresql-contrib-8.3 libpq-dev ruby ruby1.8-dev ri irb rdoc rubygems ragel memcached libmemcache-dev subversion nginx rake libopenssl-ruby mongrel
echo "Installing packages..."
apt-get -y install build-essential automake openssl libssl-dev libyaml-dev libxml2-dev libxslt-dev autoconf ncurses-dev sudo gcc g++ libreadline-dev zlib1g-dev flex bison libgd2-noxpm libgd2-noxpm-dev bzip2 ragel memcached libmemcache-dev git curl libcurl4-openssl-dev emacs-nox
# Install Ruby gems
for i in postgres diff-lcs html5 mongrel mongrel_cluster memcache-client aws-s3 json ; do gem install $i ; done
gem install rails --version=2.1.0
gem install acts_as_versioned
# Install PostgreSQL 9.1
apt-get -y install python-software-properties
add-apt-repository ppa:pitti/postgresql
apt-get update
apt-get install -y postgresql-9.1 postgresql-contrib-9.1 libpq-dev
if [ $? -ne 0 ]; then
exit 1
fi
# Install RVM
echo "Installing RVM..."
bash < <(curl -s https://rvm.beginrescueend.com/install/rvm)
echo "source /usr/local/rvm/scripts/rvm" >> /etc/bash.bashrc
echo "source /usr/local/rvm/scripts/rvm" >> /etc/profile
source /usr/local/rvm/scripts/rvm
rvm install ruby-1.9.2-p290 --with-openssl-dir=/usr/local
rvm 1.9.2 --default
# Install gems
gem install --no-ri --no-rdoc capistrano
gem install --no-ri --no-rdoc capistrano-ext
gem install --no-ri --no-rdoc bundler
# Install Passenger
gem install --no-ri --no-rdoc -v 3.0.8 passenger
rvm exec passenger-install-nginx-module
rm /opt/nginx/conf/*.default
if [ $? -ne 0 ]; then
exit 1
fi
# Create user account
useradd -m danbooru
PG_HBA_FILE="/etc/postgresql/8.3/main/pg_hba.conf"
chsh -s /bin/bash danbooru
echo "source /usr/local/rvm/scripts/rvm" > /home/danbooru/.bashrc
chmod g-wx,o-wx /home/danbooru/.bashrc
chown danbooru:danbooru /home/danbooru/.bashrc
echo "export rvm_path=/usr/local/rvm" > /etc/rvmrc
addgroup wheel
usermod -G root,wheel root
usermod -G danbooru,wheel danbooru
# Update PostgreSQL
PG_HBA_FILE="/etc/postgresql/9.1/main/pg_hba.conf"
echo "local all postgres,danbooru trust" > $PG_HBA_FILE
echo "host all postgres,danbooru 127.0.0.1/32 trust" >> $PG_HBA_FILE
/etc/init.d/postgresql-8.3 restart
# Install Danbooru
cd /var/www
svn export svn://donmai.us/danbooru/trunk danbooru
chown -R danbooru:danbooru danbooru
cd danbooru
mkdir -p public/data/sample
cd config
cp database.yml.example database.yml
cp local_config.rb.example local_config.rb
sed -i -e "s/DAN_HOSTNAME/$hostname/g" local_config.rb
sed -i -e "s/DAN_SITENAME/$sitename/g" local_config.rb
echo "--- " > mongrel_cluster.yml
echo "cwd: /var/www/danbooru" >> mongrel_cluster.yml
echo "port: \"8050\"" >> mongrel_cluster.yml
echo "environment: production" >> mongrel_cluster.yml
echo "address: 127.0.0.1" >> mongrel_cluster.yml
echo "servers: 3" >> mongrel_cluster.yml
echo "num_processors: 10" >> mongrel_cluster.yml
cd ../lib/danbooru_image_resizer
ruby extconf.rb
make
cd ../..
/etc/init.d/postgresql restart
sudo -u postgres createuser -s danbooru
sudo -u danbooru createdb danbooru
sudo -u danbooru psql danbooru < db/postgres.sql
sudo -u danbooru rake db:migrate RAILS_ENV=production
script/donmai/upbooru
# Set up nginx
DANBOORU_CONF_FILE="/etc/nginx/sites-enabled/danbooru.conf"
echo "upstream mongrel {" > $DANBOORU_CONF_FILE
echo " server 127.0.0.1:8050;" >> $DANBOORU_CONF_FILE
echo " server 127.0.0.1:8051;" >> $DANBOORU_CONF_FILE
echo " server 127.0.0.1:8052;" >> $DANBOORU_CONF_FILE
echo "}" >> $DANBOORU_CONF_FILE
echo "server {" >> $DANBOORU_CONF_FILE
echo " listen 80;" >> $DANBOORU_CONF_FILE
echo " server_name $hostname;" >> $DANBOORU_CONF_FILE
echo " root /var/www/danbooru/public;" >> $DANBOORU_CONF_FILE
echo " index index.html;" >> $DANBOORU_CONF_FILE
echo " access_log /var/www/danbooru/log/server.access.log;" >> $DANBOORU_CONF_FILE
echo " error_log /var/www/danbooru/log/server.error.log;" >> $DANBOORU_CONF_FILE
echo " client_max_body_size 30m;" >> $DANBOORU_CONF_FILE
echo " location /stylesheets {" >> $DANBOORU_CONF_FILE
echo " expires max;" >> $DANBOORU_CONF_FILE
echo " break;" >> $DANBOORU_CONF_FILE
echo " }" >> $DANBOORU_CONF_FILE
echo " location /javascripts {" >> $DANBOORU_CONF_FILE
echo " expires max;" >> $DANBOORU_CONF_FILE
echo " break;" >> $DANBOORU_CONF_FILE
echo " }" >> $DANBOORU_CONF_FILE
echo " location /data {" >> $DANBOORU_CONF_FILE
echo " valid_referers none $hostname;" >> $DANBOORU_CONF_FILE
echo " if (\$invalid_referer) {" >> $DANBOORU_CONF_FILE
echo " return 403;" >> $DANBOORU_CONF_FILE
echo " }" >> $DANBOORU_CONF_FILE
echo " expires max;" >> $DANBOORU_CONF_FILE
echo " break;" >> $DANBOORU_CONF_FILE
echo " }" >> $DANBOORU_CONF_FILE
echo " location /maintenance.html {" >> $DANBOORU_CONF_FILE
echo " expires 10;" >> $DANBOORU_CONF_FILE
echo " }" >> $DANBOORU_CONF_FILE
echo " if (-f \$document_root/maintenance.html) {" >> $DANBOORU_CONF_FILE
echo " rewrite ^(.*)\$ /maintenance.html last;" >> $DANBOORU_CONF_FILE
echo " break;" >> $DANBOORU_CONF_FILE
echo " }" >> $DANBOORU_CONF_FILE
echo " location / {" >> $DANBOORU_CONF_FILE
echo " proxy_set_header X-Real-IP \$remote_addr;" >> $DANBOORU_CONF_FILE
echo " proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;" >> $DANBOORU_CONF_FILE
echo " proxy_set_header Host \$http_host;" >> $DANBOORU_CONF_FILE
echo " proxy_redirect false;" >> $DANBOORU_CONF_FILE
echo " if (!-f \$request_filename) {" >> $DANBOORU_CONF_FILE
echo " proxy_pass http://mongrel;" >> $DANBOORU_CONF_FILE
echo " }" >> $DANBOORU_CONF_FILE
echo " }" >> $DANBOORU_CONF_FILE
echo " error_page 404 /404.html;" >> $DANBOORU_CONF_FILE
echo " error_page 500 502 503 504 /500.html;" >> $DANBOORU_CONF_FILE
echo "}" >> $DANBOORU_CONF_FILE
/etc/init.d/nginx restart
mkdir -p /var/log/www
# Setup nginx
curl -s https://raw.github.com/r888888888/danbooru/master/script/install/init_d.templ > /etc/init.d/nginx
chmod +x,g-w /etc/init.d/nginx
update-rc.d -f nginx defaults
mkdir -p /opt/nginx/conf/sites
curl -s https://raw.github.com/r888888888/danbooru/master/script/install/nginx.conf > /opt/nginx/conf/nginx.conf
curl -s https://raw.github.com/r888888888/danbooru/master/script/install/nginx.danbooru.conf > /opt/nginx/conf/sites/danbooru.conf
sed -i -e 's/\$hostname/$HOSTNAME/g' /opt/nginx/conf/sites/danbooru.conf
/etc/init.d/nginx start
echo "%wheel ALL=(ALL) ALL" >> /etc/sudoers
# Setup logrotate
LOGROTATE_CONF_FILE="/etc/logrotate.conf"
echo >> $LOGROTATE_CONF_FILE
echo "/var/log/www/danbooru.access.log" >> $LOGROTATE_CONF_FILE
echo "/var/log/www/danbooru.error.log">> $LOGROTATE_CONF_FILE
echo "/var/www/danbooru/current/log/production.log {" >> $LOGROTATE_CONF_FILE
echo " daily" >> $LOGROTATE_CONF_FILE
echo " rotate 3" >> $LOGROTATE_CONF_FILE
echo " copytruncate" >> $LOGROTATE_CONF_FILE
echo "}" >> $LOGROTATE_CONF_FILE
# Setup danbooru account
echo "*************************************************"
echo "* Enter a new password for the danbooru account *"
echo "*************************************************"
passwd danbooru
sudo -u danbooru createdb danbooru2
cd /home/danbooru
sudo -u danbooru mkdir /home/danbooru/apps
git clone git://github.com/r888888888/danbooru.git danbooru
chown -R danbooru:danbooru danbooru
cap deploy:setup
cap deploy:update_code
cap deploy:migrate
chown danbooru:danbooru /var/www/danbooru/shared/log/development.log
echo
echo "I'm done!"
echo "You should probably set the password for the danbooru account (run passwd danbooru)."
echo
echo "**************************************************************"
echo "* Danbooru has now been setup on this computer and should be *"
echo "* accessible from the web. Go ahead and create an account. *"
echo "* The first account will automatically be made an admin. You *"
echo "* can edit the configuration files by editing *"
echo "* /var/www/danbooru/shared/config/local_config and *"
echo "* /var/www/danbooru/shared/config/database.yml *"
echo "**************************************************************"

View File

@@ -1,138 +0,0 @@
Danbooru Installation guide on FreeBSD (6.2)
Provided by Shuugo
Cleanup of dovac's guide: http://uruchai.com/2007/12/24/in-depth-guide-on-installing-danbooru-on-freebsd
A minimal FreeBSD profile installation is encouraged. You can use VMWare to test how things work before trying on an actual machine.
1)) Updating ports:
You can find how fully work here: http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/ports-using.html but basically you will only need:
1. portsnap fetch
2. portsnap extract
2)) Install the following things through ports
1. cd /usr/ports/devel/mkmf/ && make install clean
2. cd /usr/ports/ftp/wget/ && make install clean
3. cd /usr/ports/editors/nano/ && make install clean
4. cd /usr/ports/devel/subversion/ && make install clean (May ask for configuration: Choose "libiconv", "python25", enable "huge stack size", and disable "ipv6"
5. cd /usr/ports/databases/memcached/ && make install clean
6. cd /usr/ports/graphics/gd/ && make install clean (Make sure you enable iconv support)
7. cd /usr/ports/databases/postgresql83-client/ && make install clean (config defaults are ok)
8. cd /usr/ports/databases/postgresql83-server/ && make install clean (config defaults are ok)
3)) Editing rc.conf for starting postgres and memcached at boot.
1. nano /etc/rc.conf
2. Add the following at the end of the file:
postgresql_enable="YES"
memcached_enable="yes"
memacached_flags="-l 127.0.0.1 -d m 100"
3. Press Control + X to save.
4. We run "/usr/local/etc/rc.d/postgresql initdb" to get ready to initialize postgres for first time.
5. Use "/usr/local/etc/rc.d/postgresql start", to start the postgresql server.
4)) Ruby on rails installation
1. cd /usr/ports/lang/ruby18/ && make install clean (Disable ipv6)
2. rubygem-rails port is broken, download it from rubyforge
2a wget http://rubyforge.org/frs/download.php/29548/rubygems-1.0.1.tgz
2b tar xvf rubygems-1.0.1.tgz
2c cd rubygems-1.0.1
2d ruby setup.rb
3. cd /usr/ports/www/rubygem-rails/ && make install clean (Be sure it's rubygem-rails-1.2.6. Rails 2.0 isn't compatible yet)
4. cd /usr/ports/www/rubygem-redcloth/ && make install clean
5. cd /usr/ports/www/rubygem-mongrel/ && make install clean
Some gems are not available through ports
6a wget http://rubyforge.org/frs/download.php/29624/postgres-0.7.9.2007.12.22.gem
6b /usr/bin/gem18 install --no-ri --install-dir /usr/local/lib/ruby/gems/1.8 ./postgres-0.7.9.2007.12.22.gem (There's a chance that it's not gem18, but gem I'll assume it's the correct path, if not, replace it on the following steps too)
7. /usr/bin/gem18 aws-s3 diff-lcs acts_as_versioned html5 (Accept all dependencies)
5)) Danbooru installation
1. Create the danbooru user, -> adduser (danbooru, and choose a password)
2. cd /home/danbooru
3. svn co svn://danbooru.donmai.us/danbooru/trunk (This will get you the latest trunk)
4. cd trunk/
5. mv * ..
6. cd ..
7. rm -r trunk/
8. Database creation:
8a su pgsql
8b CREATE DATABASE danbooru;
8c \q
8d psql -d danbooru -f /home/danbooru/db/postgres.sql
8e exit
6)) Danbooru configuration
1. cd /home/danbooru/config
2. mv database.yml.example database.yml
3. nano database.yml
3a Change all users to pgsql (Control+X to save and exit)
4. mv local_config.rb.example local_config.rb
5. nano local_config.rb
NOTE: You can check for additional configuration parameters and a brief explanation in default_config.rb
5a. Change the parameters needed an add these parameters
CONFIG["password_salt"] = “choujin-steinerr” (replace the salt with something else)
CONFIG["image_store"] = :local_flat (replace with :local_hierarchy if you want scaled folders for example /01/23/fullhash.ext, leave :local_falt to leave all the images in one same folder)
CONFIG["enable_caching"] = false (change to true to enable memcache, this will speed up things)
CONFIG["memcache_servers"] = ["localhost:4000"] (change to "localhost:11211")
5b Control + X to save and exit.
6. Compiling the resizer
6a You can rather choose between using "ruby extconf.rb" or "ruby extconf.rb --with-gd-dir=/usr/local/gd", if you are using this last option you can ignore the 6b 6c and 6d steps. Using the first method will give you always the same gd version while the second command, the gd version will be updated when you update it through ports.
6b cp /usr/local/include/gd.h gd.h
6c cp /usr/local/include/gd_io.h gd_io.h
6d cp /usr/local/include/gdfx.h gdfx.h
6e make
6f make install
7. cd /home/danbooru
7b /usr/local/bin/rake db:migrate
7)) Basic webserver
- Now you can run "mongrel_rails start", this will make danbooru public on your hostname:3000. You will see debug information in the console
- For running it with mongrel and serving it "normally" you can use "mongrel_rails start -p 80 -d" This will tell mongrel to run on port 80 and as a daemon (not displaying anything in the console)
8)) Advanced webserver
Is encouraged that you rather configure Apache or lighttpd to proxy (or vhosting) the rails app. However this last method requries advanced configuration files and server modules.
If you plan only on running danbooru here's a good configuration for lighttpd usage (you can install it through ports)
Mongrel running as a daemon (4 threads) You might want to add this to the rc.conf if you want to start it automatically
1. cd /home/danbooru
2a mongrel_rails start -d -p 8001 -e production -P log/mongrel-1.pid
2b mongrel_rails start -d -p 8002 -e production -P log/mongrel-2.pid
2c mongrel_rails start -d -p 8003 -e production -P log/mongrel-3.pid
2d mongrel_rails start -d -p 8004 -e production -P log/mongrel-4.pid
Then on lighttpd.conf be sure to have the following mods enabled (Remove # before its names if not):
-mod_rewrite
-mod_redirect
-mod_access
-mod_accesslog
-mod_compress
-mod_proxy
3. Add this to your lighttpd.conf:
proxy.balance = "fair"
proxy.server = ( "/" =>
( ( "host" => "127.0.0.1", "port" => 8001 ),
( "host" => "127.0.0.1", "port" => 8002 ),
( "host" => "127.0.0.1", "port" => 8003 ),
( "host" => "127.0.0.1", "port" => 8004 ) ) )
4. Restart lighttpd: "/usr/local/etc/rc.d/lighttpd restart"

View File

@@ -50,17 +50,7 @@
location.href = domain + "/static/terms_of_service?url=" + location.href;
return;
}
if (this.get("hide-news-ticker") == "1") {
$("#news-ticker").hide();
} else {
$("#close-news-ticker-link").click(function(e) {
$("#news-ticker").hide();
Danbooru.Cookie.put("hide-news-ticker", "1", 1);
return false;
});
}
if (this.get("hide-upgrade-account") != "1") {
$("#upgrade-account").show();
}

View File

@@ -20,6 +20,36 @@
$("a#remove-from-favorites").hide();
}
}
Danbooru.Favorite.create = function(post_id) {
Danbooru.Post.notice_update("inc");
$.ajax({
type: "POST",
url: "/favorites",
data: {
post_id: post_id
},
complete: function() {
Danbooru.Post.notice_update("dec");
},
error: function(data, status, xhr) {
Danbooru.j_alert("Error: " + data.reason);
}
});
}
Danbooru.Favorite.destroy = function(post_id) {
Danbooru.Post.notice_update("inc");
$.ajax({
type: "DELETE",
url: "/favorites/" + post_id,
complete: function() {
Danbooru.Post.notice_update("dec");
}
});
}
})();
$(document).ready(function() {

View File

@@ -5,6 +5,19 @@
$("#c-forum-topics #preview").hide();
this.initialize_preview_link();
this.initialize_last_forum_read_at();
}
Danbooru.ForumPost.initialize_last_forum_read_at = function() {
var last_forum_read_at = Date.parse(Danbooru.meta("last-forum-read-at"));
$("#c-forum-topics #a-index time").each(function(i, x) {
var $x = $(x);
var $date = Date.parse($x.attr("datetime"));
if (Date.parse($x.attr("datetime")) > last_forum_read_at) {
$x.closest("tr").addClass("new-topic");
}
});
}
Danbooru.ForumPost.initialize_preview_link = function() {

View File

@@ -0,0 +1,21 @@
(function() {
Danbooru.News = {};
Danbooru.News.initialize = function() {
var key = $("#news-ticker").data("updated-at");
if (Danbooru.Cookie.get("news-ticker") === key) {
$("#news-ticker").hide();
} else {
$("#close-news-ticker-link").click(function(e) {
$("#news-ticker").hide();
Danbooru.Cookie.put("news-ticker", key);
return false;
});
}
}
$(function() {
Danbooru.News.initialize();
});
})();

View File

@@ -0,0 +1,83 @@
(function() {
Danbooru.PostModeMenu = {};
Danbooru.PostModeMenu.initialize = function() {
this.initialize_selector();
this.initialize_preview_link();
}
Danbooru.PostModeMenu.initialize_selector = function() {
if (Danbooru.Cookie.get("mode") === "") {
Danbooru.Cookie.put("mode", "view");
$("#mode-box select").val("view");
} else {
$("#mode-box select").val(Danbooru.Cookie.get("mode"));
}
$("#mode-box select").click(Danbooru.PostModeMenu.change);
}
Danbooru.PostModeMenu.initialize_preview_link = function() {
$(".post-preview a").click(Danbooru.PostModeMenu.click);
}
Danbooru.PostModeMenu.change = function() {
var s = $("#mode-box select").val();
var $body = $(document.body);
$body.removeClass();
$body.addClass("mode-" + s);
Danbooru.Cookie.put("mode", s, 7);
if (s === "edit-tag-script") {
var script = Danbooru.Cookie.get("tag-script");
script = prompt("Enter a tag script", script);
if (script) {
Cookie.put("tag-script", script);
$("#mode-box select").val("apply-tag-script");
} else {
$("#mode-box select").val("view");
}
this.change();
}
}
Danbooru.PostModeMenu.click = function(e) {
var s = $("#mode-box select").val();
var post_id = $(e.target).closest("article").data("id");
if (s === "add-fav") {
Danbooru.Favorite.create(post_id);
} else if (s === "remove-fav") {
Danbooru.Favorite.destroy(post_id);
} else if (s === "edit") {
// TODO
} else if (s === 'vote-down') {
Danbooru.Post.vote("down", post_id);
} else if (s === 'vote-up') {
Danbooru.Post.vote("up", post_id);
} else if (s === 'rating-q') {
Danbooru.Post.update(post_id, {"post[rating]": "q"});
} else if (s === 'rating-s') {
Danbooru.Post.update(post_id, {"post[rating]": "s"});
} else if (s === 'rating-e') {
Danbooru.Post.update(post_id, {"post[rating]": "e"});
} else if (s === 'lock-rating') {
Danbooru.Post.update(post_id, {"post[is_rating_locked]": "1"});
} else if (s === 'lock-note') {
Danbooru.Post.update(post_id, {"post[is_note_locked]": "1"});
} else if (s === "apply-tag-script") {
var tag_script = Danbooru.Cookie.get("tag-script");
Danbooru.TagScript.run(post_id, tag_script);
} else {
return;
}
e.preventDefault();
}
})();
$(function() {
Danbooru.PostModeMenu.initialize();
});

View File

@@ -1,170 +1,8 @@
// PostModeMenu = {
// init: function() {
// this.original_background_color = $(document.body).css("background-color")
//
// if (Cookie.get("mode") == "") {
// Cookie.put("mode", "view");
// $("#mode-box select").val("view");
// } else {
// $("#mode-box select").val(Cookie.get("mode"));
// }
//
// // this.change();
// },
//
// change: function() {
// var s = $("#mode-box select").val();
// Cookie.put("mode", s, 7);
//
// if (s == "view") {
// $(document.body).css({"background-color": this.original_background_color});
// } else if (s == "edit") {
// $(document.body).css({"background-color": "#3A3"});
// } else if (s == "add-fav") {
// $(document.body).css({"background-color": "#FFA"});
// } else if (s == "remove-fav") {
// $(document.body).css({"background-color": "#FFA"});
// } else if (s == "rating-q") {
// $(document.body).css({"background-color": "#AAA"});
// } else if (s == "rating-s") {
// $(document.body).css({"background-color": "#6F6"});
// } else if (s == "rating-e") {
// $(document.body).css({"background-color": "#F66"});
// } else if (s == "vote-down") {
// $(document.body).css({"background-color": "#FAA"});
// } else if (s == "vote-up") {
// $(document.body).css({"background-color": "#AFA"});
// } else if (s == "lock-rating") {
// $(document.body).css({"background-color": "#AA3"});
// } else if (s == "lock-note") {
// $(document.body).css({"background-color": "#3AA"});
// } else if (s == "approve") {
// $(document.body).css({"background-color": "#26A"});
// } else if (s == "unapprove") {
// $(document.body).css({"background-color": "#F66"});
// } else if (s == "add-to-pool") {
// $(document.body).css({"background-color": "#26A"});
// } else if (s == "apply-tag-script") {
// $(document.body).css({"background-color": "#A3A"});
// } else if (s == "edit-tag-script") {
// $(document.body).css({"background-color": "#FFF"});
//
// var script = Cookie.get("tag-script");
// script = prompt("Enter a tag script", script);
//
// if (script) {
// Cookie.put("tag-script", script);
// $("#mode-box select").val("apply-tag-script");
// } else {
// $("#mode-box select").val("view");
// }
//
// this.change();
// } else {
// $(document.body).css({"background-color": "#AFA"});
// }
// },
//
// click: function(post_id) {
// var s = $("#mode-box select").val();
//
// if (s.value == "view") {
// return true;
// } else if (s.value == "add-fav") {
// Favorite.create(post_id);
// } else if (s.value == "remove-fav") {
// Favorite.destroy(post_id);
// } else if (s.value == "edit") {
// // TODO
// } else if (s.value == 'vote-down') {
// PostVote.create("down", post_id);
// } else if (s.value == 'vote-up') {
// PostVote.create("up", post_id);
// } else if (s.value == 'rating-q') {
// Post.update(post_id, {"post[rating]": "questionable"});
// } else if (s.value == 'rating-s') {
// Post.update(post_id, {"post[rating]": "safe"});
// } else if (s.value == 'rating-e') {
// Post.update(post_id, {"post[rating]": "explicit"});
// } else if (s.value == 'lock-rating') {
// Post.update(post_id, {"post[is_rating_locked]": "1"});
// } else if (s.value == 'lock-note') {
// Post.update(post_id, {"post[is_note_locked]": "1"});
// } else if (s.value == 'unapprove') {
// Unapproval.create(post_id);
// } else if (s.value == "approve") {
// Post.update(post_id, {"post[is_pending]": "0"});
// } else if (s.value == 'add-to-pool') {
// Pool.add_post(post_id, 0);
// } else if (s.value == "apply-tag-script") {
// var tag_script = Cookie.get("tag-script");
// TagScript.run(post_id, tag_script);
// }
//
// return false;
// }
// }
//
// TagScript = {
// parse: function(script) {
// return script.match(/\[.+?\]|\S+/g);
// },
//
// test: function(tags, predicate) {
// var split_pred = predicate.match(/\S+/g);
// var is_true = true;
//
// split_pred.each(function(x) {
// if (x[0] == "-") {
// if (tags.include(x.substr(1, 100))) {
// is_true = false;
// throw $break;
// }
// } else {
// if (!tags.include(x)) {
// is_true = false;
// throw $break;
// }
// }
// })
//
// return is_true
// },
//
// process: function(tags, command) {
// if (command.match(/^\[if/)) {
// var match = command.match(/\[if\s+(.+?)\s*,\s*(.+?)\]/)
// if (TagScript.test(tags, match[1])) {
// return TagScript.process(tags, match[2]);
// } else {
// return tags;
// }
// } else if (command == "[reset]") {
// return [];
// } else if (command[0] == "-") {
// return tags.reject(function(x) {return x == command.substr(1, 100)})
// } else {
// tags.push(command)
// return tags;
// }
// },
//
// run: function(post_id, tag_script) {
// var commands = TagScript.parse(tag_script);
// var post = Post.posts.get(post_id);
// var old_tags = post.tags.join(" ");
//
// commands.each(function(x) {
// post.tags = TagScript.process(post.tags, x);
// })
//
// Post.update(post_id, {"post[old_tags]": old_tags, "post[tags]": post.tags.join(" ")});
// }
// }
(function() {
Danbooru.Post = {};
Danbooru.Post.pending_update_count = 0;
Danbooru.Post.initialize_all = function() {
this.initialize_post_sections();
this.initialize_wiki_page_excerpt();
@@ -192,7 +30,7 @@
Danbooru.Cookie.put("hide-wiki-page-excerpt", "0");
});
}
Danbooru.Post.initialize_post_sections = function() {
$("#post-sections li a").click(function(e) {
$("#comments").hide();
@@ -209,11 +47,68 @@
$("#notes").hide();
$("#edit").hide();
}
Danbooru.Post.notice_update = function(x) {
if (x === "inc") {
Danbooru.Post.pending_update_count += 1;
Danbooru.notice("Updating posts (" + Danbooru.Post.pending_update_count + " pending)...");
} else {
Danbooru.Post.pending_update_count -= 1;
if (Danbooru.Post.pending_update_count < 1) {
Danbooru.notice("Posts updated");
} else {
Danbooru.notice("Updating posts (" + Post.pending_update_count + " pending)...");
}
}
}
Danbooru.Post.update_data = function(data) {
var $post = $("#post_" + data.id);
$post.data("tags", data.tags);
}
Danbooru.Post.vote = function(score, id) {
Danbooru.Post.notice_update("inc");
$.ajax({
type: "POST",
url: "/posts/" + id + "/votes",
data: {
score: score
},
complete: function() {
Danbooru.Post.notice_update("dec");
},
success: function(data, status, xhr) {
$("post-score-" + data.post_id).html(data.score);
},
error: function(data, status, xhr) {
Danbooru.notice("Error: " + data.reason);
}
});
}
Danbooru.Post.update = function(post_id, params) {
Danbooru.Post.notice_update("inc");
$.ajax({
type: "PUT",
url: "/posts/" + post_id + ".json",
data: params,
complete: function() {
Danbooru.Post.notice_update("dec");
},
success: function(data, status, xhr) {
Danbooru.Post.update_data(data);
},
error: function(data, status, xhr) {
Danbooru.j_alert("Error: " + data.reason);
}
});
}
})();
$(document).ready(function() {
// $("#mode-box select").click(PostModeMenu.change);
// PostModeMenu.init();
Danbooru.Post.initialize_all();
});

View File

@@ -0,0 +1,56 @@
(function() {
Danbooru.TagScript = {};
Danbooru.TagScript.parse = function(script) {
return script.match(/\[.+?\]|\S+/g);
}
Danbooru.TagScript.test = function(tags, predicate) {
var split_pred = predicate.match(/\S+/g);
var is_true = true;
$.each(split_pred, function(i, x) {
if (x[0] === "-") {
if (tags.include(x.substr(1, 100))) {
is_true = false;
}
} else {
if (!tags.include(x)) {
is_true = false;
}
}
});
return is_true;
}
Danbooru.TagScript.process = function(tags, command) {
if (command.match(/^\[if/)) {
var match = command.match(/\[if\s+(.+?)\s*,\s*(.+?)\]/)
if (this.test(tags, match[1])) {
return this.process(tags, match[2]);
} else {
return tags;
}
} else if (command === "[reset]") {
return [];
} else if (command[0] === "-") {
return Danbooru.reject(tags, function(x) {return x === command.substr(1, 100)});
} else {
tags.push(command)
return tags;
}
}
Danbooru.TagScript.run = function(post_id, tag_script) {
var commands = this.parse(tag_script);
var post = $("#p_" + post_id);
var old_tags = post.data("tags");
$.each(commands, function(i, x) {
post.data("tags", Danbooru.TagScript.process(post.data("tags"), x));
})
Danbooru.Post.update(post_id, {"post[old_tags]": old_tags, "post[tags]": post.data("tags")});
}
})();

View File

@@ -1,4 +1,4 @@
$(document).ready(function() {
$(function() {
var img = $("#image-preview img");
if (img) {
var height = img.attr("height");
@@ -7,7 +7,7 @@ $(document).ready(function() {
var ratio = 400.0 / height;
img.attr("height", height * ratio);
img.attr("width", width * ratio);
$("#scale").val("Scaled " + parseInt(100 * ratio) + "%");
$("#scale").html("Scaled " + parseInt(100 * ratio) + "%");
}
}
});

View File

@@ -3,6 +3,10 @@
return $("meta[name=" + key + "]").attr("content");
}
Danbooru.notice = function(msg) {
$('#notice').html(msg).show();
}
Danbooru.j_alert = function(title, msg) {
$('<div title="' + title + '"></div>').html(msg).dialog();
}
@@ -30,4 +34,14 @@
return all;
}
Danbooru.reject = function(array, f) {
var filtered = [];
$.each(array, function(i, x) {
if (!f(x)) {
filtered.push(x);
}
});
return filtered;
}
})();

View File

@@ -896,6 +896,10 @@ div#c-forum-topics {
color: #AAA;
}
tr.new-topic {
font-weight: bold;
}
div#form-content {
float: left;
width: 450px;
@@ -1079,7 +1083,7 @@ footer#page-footer {
margin: 1em;
text-align: center;
padding-top: 1em;
border-top: 2px solid #CCC;
border-top: 1px solid #EEE;
}
/*** news ticker ***/
@@ -1108,3 +1112,69 @@ div#news-ticker {
float: right;
}
}
/*** post mode menus ***/
body#mode-view {
background-color: "#FFF";
}
body#mode-edit {
background-color: "#3A3";
}
body#mode-add-fav {
background-color: "#FFA";
}
body#mode-remove-fav {
background-color: "#FFA";
}
body#mode-rating-q {
background-color: "#AAA";
}
body#mode-rating-s {
background-color: "#6F6";
}
body#mode-rating-e {
background-color: "#F66";
}
body#mode-vote-down {
background-color: "#FAA";
}
body#mode-vote-up {
background-color: "#AFA";
}
body#mode-lock-rating {
background-color: "#AA3";
}
body#mode-lock-note {
background-color: "#3AA";
}
body#mode-approve {
background-color: "#26A";
}
body#mode-unapprove {
background-color: "#F66";
}
body#mode-add-to-pool {
background-color: "#26A";
}
body#mode-apply-tag-script {
background-color: "#A3A";
}
body#mode-edit-tag-script {
background-color: "#FFF";
}

View File

@@ -12,6 +12,11 @@ class ArtistsController < ApplicationController
respond_with(@artist)
end
def banned
@artists = Artist.where("is_banned = ?", true).order("name")
respond_with(@artists)
end
def index
@search = Artist.search(params[:search])
@artists = @search.paginate(params[:page])

View File

@@ -2,6 +2,7 @@ class ForumTopicsController < ApplicationController
respond_to :html, :xml, :json
before_filter :member_only, :except => [:index, :show]
before_filter :normalize_search, :only => :index
before_filter :update_last_forum_read_at, :only => [:index, :show]
rescue_from User::PrivilegeError, :with => "static/access_denied"
def new
@@ -56,6 +57,12 @@ private
forum_topic.is_sticky = params[:forum_topic][:is_sticky]
end
def update_last_forum_read_at
return if CurrentUser.last_forum_read_at.present? && CurrentUser.last_forum_read_at > 1.day.ago
CurrentUser.update_column(:last_forum_read_at, Time.now)
end
def normalize_search
if params[:title_matches]
params[:search] ||= {}

View File

@@ -6,6 +6,7 @@ class SessionsController < ApplicationController
def create
if User.authenticate(params[:name], params[:password])
@user = User.find_by_name(params[:name])
@user.update_column(:last_logged_in_at, Time.now)
session[:user_id] = @user.id
redirect_to(params[:url] || session[:previous_uri] || posts_path, :notice => "You are now logged in.")
else

View File

@@ -23,6 +23,7 @@ class UploadsController < ApplicationController
def create
@upload = Upload.create(params[:upload])
@upload.delay.process!
respond_with(@upload)
end

View File

@@ -22,6 +22,7 @@ class UsersController < ApplicationController
def show
@user = User.find(params[:id])
@presenter = UserPresenter.new(@user)
respond_with(@user)
end

View File

@@ -22,7 +22,7 @@ module AdvertisementsHelper
def render_rss_advertisement
if Danbooru.config.can_user_see_ads?(CurrentUser.user)
render :partial => "static/jlist_rss_ads"
render "static/jlist_rss_ads"
end
end
end

View File

@@ -23,13 +23,20 @@ module ApplicationHelper
end
end
def time_tag(content = nil, time)
zone = time.strftime("%z")
datetime = time.strftime("%Y-%m-%dT%H:%M" + zone[0, 3] + ":" + zone[3, 2])
content_tag(:time, content || datetime, :datetime => datetime)
end
def compact_time(time)
if time > Time.now.beginning_of_day
time.strftime("%H:%M")
time_tag(time.strftime("%H:%M"), time)
elsif time > Time.now.beginning_of_year
time.strftime("%b %e")
time_tag(time.strftime("%b %e"), time)
else
time.strftime("%b %e, %Y")
time_tag(time.strftime("%b %e, %Y"), time)
end
end
@@ -62,7 +69,7 @@ protected
when "uploads"
/^\/post/
when "post_versions"
when "post_versions", "explore/posts"
/^\/post/
when "pool_versions"

View File

@@ -112,6 +112,13 @@ class AnonymousUser
[]
end
def last_forum_read_at
Time.now
end
def update_column(*params)
end
%w(member banned privileged contributor janitor moderator admin).each do |name|
define_method("is_#{name}?") do
false

View File

@@ -0,0 +1,23 @@
class RemoteFileManager
attr_reader :path
def initialize(path)
@path = path
end
def distribute
Danbooru.config.other_server_hosts.each do |hostname|
Net::SFTP.start(hostname, Danbooru.config.remote_server_login) do |ftp|
ftp.upload!(path, path)
end
end
end
def delete
Danbooru.config.other_server_hosts.each do |hostname|
Net::SFTP.start(hostname, Danbooru.config.remote_server_login) do |ftp|
ftp.remove(path)
end
end
end
end

View File

@@ -0,0 +1,44 @@
require 'base64'
require 'digest/md5'
class AmazonBackup < ActiveRecord::Base
def self.last_id
first.last_id
end
def self.update_id(new_id)
first.update_column(:last_id, new_id)
end
def self.execute
last_id = AmazonBackup.last_id
Post.where("id > ?", last_id).limit(200).order("id").each do |post|
AWS::S3::Base.establish_connection!(
:access_key_id => Danbooru.config.amazon_s3_access_key_id,
:secret_access_key => Danbooru.config.amazon_s3_secret_access_key
)
if File.exists?(post.file_path)
base64_md5 = Base64.encode64(Digest::MD5.digest(File.read(post.file_path)))
AWS::S3::S3Object.store(post.file_name, open(post.file_path, "rb"), Danbooru.config.amazon_s3_bucket_name, "Content-MD5" => base64_md5)
end
if post.image? && File.exists?(post.preview_file_path)
AWS::S3::S3Object.store("preview/#{post.md5}.jpg", open(post.preview_file_path, "rb"), Danbooru.config.amazon_s3_bucket_name)
end
if File.exists?(post.medium_file_path)
AWS::S3::S3Object.store("medium/#{post.md5}.jpg", open(post.medium_file_path, "rb"), Danbooru.config.amazon_s3_bucket_name)
end
if File.exists?(post.large_file_path)
AWS::S3::S3Object.store("large/#{post.md5}.jpg", open(post.large_file_path, "rb"), Danbooru.config.amazon_s3_bucket_name)
end
AmazonBackup.update_id(last_id)
end
rescue Exception => x
# probably some network error, retry next time
end
end

View File

@@ -166,6 +166,10 @@ class Artist < ActiveRecord::Base
include NoteMethods
include TagMethods
def ban!
end
def initialize_creator
self.creator_id = CurrentUser.user.id
end

View File

@@ -1,27 +0,0 @@
module Jobs
class BackupToS3 < Struct.new(:last_id)
def perform
Post.find(:all, :conditions => ["id > ?", last_id], :limit => 200, :order => "id").each do |post|
AWS::S3::Base.establish_connection!(:access_key_id => CONFIG["amazon_s3_access_key_id"], :secret_access_key => CONFIG["amazon_s3_secret_access_key"])
if File.exists?(post.file_path)
base64_md5 = Base64.encode64(Digest::MD5.digest(File.read(post.file_path)))
AWS::S3::S3Object.store(post.file_name, open(post.file_path, "rb"), CONFIG["amazon_s3_bucket_name"], "Content-MD5" => base64_md5)
end
if post.image? && File.exists?(post.preview_path)
AWS::S3::S3Object.store("preview/#{post.md5}.jpg", open(post.preview_path, "rb"), CONFIG["amazon_s3_bucket_name"])
end
if File.exists?(post.sample_path)
AWS::S3::S3Object.store("sample/" + CONFIG["sample_filename_prefix"] + "#{post.md5}.jpg", open(post.sample_path, "rb"), CONFIG["amazon_s3_bucket_name"])
end
self.last_id = post.id
end
Delayed::Job.enqueue(BackupToS3.new(last_id))
rescue Exception => x
# probably some network error, retry next time
end
end
end

View File

@@ -1,7 +0,0 @@
module Jobs
class CalculatePostCount < Struct.new(:tag_name)
def perform
Tag.recalculate_post_count(tag_name)
end
end
end

View File

@@ -1,12 +0,0 @@
module Jobs
class CalculateRelatedTags < Struct.new(:tag_id)
def perform
tag = Tag.find_by_id(tag_id)
if tag
tag.update_related
tag.save
end
end
end
end

View File

@@ -1,13 +0,0 @@
module Jobs
class CalculateUploadedTags < Struct.new(:user_id)
def perform
tags = []
user = User.find(user_id)
CONFIG["tag_types"].values.uniq.each do |tag_type|
tags += user.calculate_uploaded_tags(tag_type)
end
user.update_column(:uploaded_tags, tags.join("\n"))
end
end
end

View File

@@ -1,12 +0,0 @@
module Jobs
class CreateTagAlias < Struct.new(:antecedent_name, :consequent_name, :creator_id, :creator_ip_addr)
def execute
TagAlias.create(
:antecedent_name => antecedent_name,
:consequent_name => consequent_name,
:creator_id => creator_id,
:creator_ip_addr => creator_ip_addr
)
end
end
end

View File

@@ -1,12 +0,0 @@
module Jobs
class CreateTagImplication < Struct.new(:antecedent_name, :consequent_name, :creator_id, :creator_ip_addr)
def perform
TagImplication.create(
:antecedent_name => antecedent_name,
:consequent_name => consequent_name,
:creator_id => creator_id,
:creator_ip_addr => creator_ip_addr
)
end
end
end

View File

@@ -1,13 +0,0 @@
module Jobs
class FixPixivUploads < Struct.new(:last_post_id)
def perform
post_id = nil
Post.find_each(:conditions => ["GREATEST(width, height) IN (150, 600) AND source LIKE ? AND id > ?", "%pixiv%", last_post_id]) do |post|
post_id = post.id
end
update_attributes(:data => {:last_post_id => post_id})
end
end
end

View File

@@ -1,7 +0,0 @@
module Jobs
class MassTagEdit < Struct.new(:start_tags, :result_tags, :updater_id, :updater_ip_addr)
def perform
Tag.mass_edit(start_tags, result_tags, updater_id, updater_ip_addr)
end
end
end

View File

@@ -1,10 +0,0 @@
module Jobs
class ProcessTagSubscriptions < Struct.new(:last_run)
def perform
if last_run.nil? || last_run < 20.minutes.ago
TagSubscription.process_all
Delayed::Job.enqueue(ProcessTagSubscriptions.new(Time.now))
end
end
end
end

View File

@@ -1,9 +0,0 @@
module Jobs
class ProcessUploads
def perform
Upload.find_each(:conditions => ["status = ?", "pending"]) do |upload|
upload.process!
end
end
end
end

View File

@@ -5,6 +5,7 @@ class Post < ActiveRecord::Base
attr_accessor :old_tag_string, :old_parent_id
after_destroy :delete_files
after_destroy :delete_remote_files
after_save :create_version
after_save :update_parent_on_save
before_save :merge_old_tags
@@ -61,11 +62,28 @@ class Post < ActiveRecord::Base
}
module FileMethods
def distribute_files
RemoteFileManager.new(file_path).distribute
RemoteFileManager.new(real_preview_file_path).distribute
RemoteFileManager.new(ssd_preview_file_path).distribute if Danbooru.config.ssd_path
RemoteFileManager.new(medium_file_path).distribute if has_medium?
RemoteFileManager.new(large_file_path).distribute if has_large?
end
def delete_remote_files
RemoteFileManager.new(file_path).delete
RemoteFileManager.new(real_preview_file_path).delete
RemoteFileManager.new(ssd_preview_file_path).delete if Danbooru.config.ssd_path
RemoteFileManager.new(medium_file_path).delete if has_medium?
RemoteFileManager.new(large_file_path).delete if has_large?
end
def delete_files
FileUtils.rm_f(file_path)
FileUtils.rm_f(medium_file_path)
FileUtils.rm_f(large_file_path)
FileUtils.rm_f(preview_file_path)
FileUtils.rm_f(ssd_preview_file_path) if Danbooru.config.ssd_path
FileUtils.rm_f(real_preview_file_path)
end
def file_path_prefix
@@ -91,9 +109,21 @@ class Post < ActiveRecord::Base
file_path
end
end
def real_preview_file_path
"#{Rails.root}/public/data/preview/#{file_path_prefix}#{md5}.jpg"
end
def ssd_preview_file_path
"#{Danbooru.config.ssd_path}/public/data/preview/#{file_path_preview}#{md5}.jpg"
end
def preview_file_path
"#{Rails.root}/public/data/preview/#{file_path_prefix}#{md5}.jpg"
if Danbooru.config.ssd_path
ssd_preview_file_path
else
real_preview_file_path
end
end
def file_url
@@ -117,7 +147,11 @@ class Post < ActiveRecord::Base
end
def preview_file_url
"/data/preview/#{file_path_prefix}#{md5}.jpg"
if Danbooru.config.ssd_path
"/ssd/data/preview/#{file_path_prefix}#{md5}.jpg"
else
"/data/preview/#{file_path_prefix}#{md5}.jpg"
end
end
def file_url_for(user)

View File

@@ -48,6 +48,8 @@ class Upload < ActiveRecord::Base
module ConversionMethods
def process!
return if status =~ /processing|completed|error/
CurrentUser.scoped(uploader, uploader_ip_addr) do
update_attribute(:status, "processing")
if is_downloadable?
@@ -64,6 +66,7 @@ class Upload < ActiveRecord::Base
generate_resizes(file_path)
move_file
post = convert_to_post
post.distribute_files
if post.save
update_attributes(:status => "completed", :post_id => post.id)
else
@@ -231,7 +234,7 @@ class Upload < ActiveRecord::Base
end
def temp_file_path
@temp_file_path ||= File.join(Rails.root, "tmp", "upload_#{Time.now.to_f}.#{$PROCESS_ID}")
@temp_file_path ||= File.join(Rails.root, "tmp", "upload_#{Time.now.to_f}.#{Process.pid}")
end
end
@@ -258,7 +261,7 @@ class Upload < ActiveRecord::Base
self.file_path = temp_file_path
if file.tempfile
if file.respond_to?(:tempfile) && file.tempfile
FileUtils.cp(file.tempfile.path, file_path)
else
File.open(file_path, 'wb') do |out|
@@ -279,6 +282,10 @@ class Upload < ActiveRecord::Base
status == "pending"
end
def is_processing?
status == "processing"
end
def is_completed?
status == "completed"
end

View File

@@ -30,7 +30,7 @@ class User < ActiveRecord::Base
has_many :feedback, :class_name => "UserFeedback", :dependent => :destroy
has_many :posts, :foreign_key => "uploader_id"
has_one :ban
has_many :subscriptions, :class_name => "TagSubscription"
has_many :subscriptions, :class_name => "TagSubscription", :foreign_key => "creator_id"
has_many :note_versions, :foreign_key => "updater_id"
belongs_to :inviter, :class_name => "User"
scope :named, lambda {|name| where(["lower(name) = ?", name])}

View File

@@ -5,8 +5,4 @@ class ForumTopicPresenter < Presenter
@forum_posts = forum_posts
@forum_topic = forum_topic
end
def pagination_html(template)
Paginators::ForumTopic.new(forum_topic, forum_posts).numbered_pagination_html(template)
end
end

View File

@@ -26,9 +26,9 @@ class PostPresenter < Presenter
return template.content_tag("p", "You need a privileged account to see this image.") if !Danbooru.config.can_user_see_post?(CurrentUser.user, @post)
if @post.is_flash?
template.render(:partial => "posts/partials/show/flash", :locals => {:post => @post})
template.render("posts/partials/show/flash", :post => @post)
elsif @post.is_image?
template.render(:partial => "posts/partials/show/image", :locals => {:post => @post})
template.render("posts/partials/show/image", :post => @post)
end
end

View File

@@ -18,7 +18,7 @@ class PostSetPresenter < Presenter
html = "<div class='post-previews'>"
if posts.empty?
return template.render(:partial => "post_sets/blank")
return template.render("post_sets/blank")
end
posts.each do |post|

View File

@@ -8,7 +8,7 @@ module PostSetPresenters
html = ""
if posts.empty?
return template.render(:partial => "post_sets/blank")
return template.render("post_sets/blank")
end
posts.each do |post|

View File

@@ -1,7 +1,7 @@
module PostSetPresenters
class Popular < Base
attr_accessor :post_set, :tag_set_presenter
delegate :posts, :date, :to => :post_set
delegate :posts, :date, :min_date, :max_date, :to => :post_set
def initialize(post_set)
@post_set = post_set
@@ -30,5 +30,15 @@ module PostSetPresenters
def next_month
1.month.since(date)
end
def range_text
if min_date == max_date
date.strftime("%B %d, %Y")
elsif max_date - min_date == 6
min_date.strftime("Week of %B %d, %Y")
else
date.strftime("%B %Y")
end
end
end
end

View File

@@ -5,6 +5,10 @@ class UserPresenter
@user = user
end
def join_date
user.created_at.strftime("%Y-%m-%d")
end
def level
user.level_string
end
@@ -26,7 +30,7 @@ class UserPresenter
def upload_limit
deleted_count = Post.for_user(user.id).deleted.count
pending_count = Post.for_user(user.id).pending.count
approved_count = Post.where("is_flagged = false and is_pending = false and user_id = ?", user.id).count
approved_count = Post.where("is_flagged = false and is_pending = false and uploader_id = ?", user.id).count
if user.base_upload_limit
limit = user.base_upload_limit - pending_count
@@ -89,7 +93,7 @@ class UserPresenter
if user.inviter_id
template.link_to(user.inviter.name, template.user_path(user.inviter_id))
else
nil
"None"
end
end
@@ -102,6 +106,16 @@ class UserPresenter
neutral = UserFeedback.for_user(user.id).neutral.count
negative = UserFeedback.for_user(user.id).negative.count
template.link_to("positive:#{positive} neutral:#{neutral} negative:#{negative}", user_feedbacks_path(:search => {:user_id_rq => user.id}))
template.link_to("positive:#{positive} neutral:#{neutral} negative:#{negative}", template.user_feedbacks_path(:search => {:user_id_rq => user.id}))
end
def subscriptions(template)
if user.subscriptions.any?
user.subscriptions.map do |subscription|
template.link_to(subscription.name, template.posts_path(:tags => "sub:#{user.name}:#{subscription.name}"))
end.join(", ").html_safe
else
"None"
end
end
end

View File

@@ -1,3 +1,9 @@
<%= image_tag(@advertisement.image_url) %>
<%= render "form" %>
<div id="c-advertisements">
<div id="a-edit">
<h1>Edit Advertisement</h1>
<%= image_tag(@advertisement.image_url) %>
<%= render "form" %>
</div>
</div>
<%= render "secondary_links" %>

View File

@@ -1,22 +1,26 @@
<h4>Advertisements</h4>
<div id="c-advertisements">
<div id="c-index">
<h1>Advertisements</h1>
<table width="100%" class="highlightable">
<thead>
<tr>
<th width="5%"></th>
<th width="5%" style="text-align: right;">Hits</th>
<th width="90%"></th>
</tr>
</thead>
<tbody>
<% @advertisements.each do |advertisement| %>
<tr>
<td><%= image_tag(advertisement.image_url, :width => advertisement.preview_width, :height => advertisement.preview_height) %></td>
<td style="text-align: right;"><%= advertisement.hits.between(@start_date, @end_date).count %></td>
<td><%= link_to "Edit", edit_advertisement_path(advertisement) %></td>
</tr>
<% end %>
</tbody>
</table>
<table width="100%" class="highlightable">
<thead>
<tr>
<th width="5%"></th>
<th width="5%" style="text-align: right;">Hits</th>
<th width="90%"></th>
</tr>
</thead>
<tbody>
<% @advertisements.each do |advertisement| %>
<tr>
<td><%= image_tag(advertisement.image_url, :width => advertisement.preview_width, :height => advertisement.preview_height) %></td>
<td style="text-align: right;"><%= advertisement.hits.between(@start_date, @end_date).count %></td>
<td><%= link_to "Edit", edit_advertisement_path(advertisement) %></td>
</tr>
<% end %>
</tbody>
</table>
</div>
</div>
<%= render "secondary_links" %>

View File

@@ -1,3 +1,9 @@
<%= error_messages_for :advertisement %>
<%= render "form" %>
<div id="c-advertisements">
<div id="a-new">
<h1>New Advertisement</h1>
<%= error_messages_for :advertisement %>
<%= render "form" %>
</div>
</div>
<%= render "secondary_links" %>

View File

@@ -1,7 +1,14 @@
<div><%= image_tag(@advertisement.image_url, :width => @advertisement.preview_width, :height => @advertisement.preview_height) %></div>
<div id="c-advertisements">
<div id="a-show">
<h1>Show Advertisement</h1>
<%= image_tag(@advertisement.image_url, :width => @advertisement.preview_width, :height => @advertisement.preview_height) %>
<ul>
<li>Hits: <%= @advertisement.hits.between(@start_date, @end_date).count %></li>
</ul>
</div>
</div>
<ul>
<li>Hits: <%= @advertisement.hits.between(@start_date, @end_date).count %></li>
</ul>
<%= render "secondary_links" %>

View File

@@ -0,0 +1,13 @@
<div id="c-artists">
<div id="a-banned">
<h1>Banned Artists</h1>
<p>The following artists have requested they be removed from the site. Please do not upload any works from these artists. These artists all have implications pointing to the <code>banned_artist</code> tag.</p>
<ul>
<% @artists.each do |artist| %>
<li><%= link_to artist.name, artist_path(artist) %></li>
<% end %>
</ul>
</div>
</div>

View File

@@ -1,5 +1,7 @@
<div id="c-artists">
<div id="a-index">
<h1>Artists</h1>
<table class="striped" width="100%">
<thead>
<tr>

View File

@@ -1,7 +1,7 @@
<div class="bans">
<div class="new">
<h1>Edit Ban</h1>
<%= render :partial => "form", :locals => {:ban => @ban} %>
<%= render "form", :ban => @ban %>
</div>
</div>

View File

@@ -1,5 +1,7 @@
<div class="bans">
<div class="index">
<h1>Bans</h1>
<table>
<thead>
<tr>

View File

@@ -1,7 +1,7 @@
<div class="bans">
<div class="new">
<h1>New Ban</h1>
<%= render :partial => "form", :locals => {:ban => @ban} %>
<%= render "form", :ban => @ban %>
</div>
</div>

View File

@@ -0,0 +1 @@
$("div.comments-for-post[data-post-id=<%= @comment.post_id %>] div.list-of-comments").append("<%= escape_javascript(render('comments/partials/show/comment', :comment => @comment)) %>");

View File

@@ -1 +0,0 @@
page.insert_html(:bottom, "div.comments-for-post[data-post-id=#{@comment.post_id}] div.list-of-comments", :partial => "comments/partials/show/comment", :locals => {:comment => @comment})

View File

@@ -1,9 +1,11 @@
<div id="c-comments">
<div id="a-index">
<h1>Comments</h1>
<div class="comments-for-post">
<div class="list-of-comments">
<% @comments.each do |comment| %>
<%= render :partial => "comments/partials/show/comment", :locals => {:post => comment.post, :comment => comment, :show_header => false} %>
<%= render "comments/partials/show/comment", :post => comment.post, :comment => comment, :show_header => false %>
<% end %>
</div>
</div>

View File

@@ -11,7 +11,7 @@
<div class="preview">
<%= link_to(image_tag(post.preview_file_url), post_path(post)) %>
</div>
<%= render :partial => "comments/partials/index/list", :locals => {:post => post, :comments => post.comments.recent.reverse, :show_header => true} %>
<%= render "comments/partials/index/list", :post => post, :comments => post.comments.recent.reverse, :show_header => true %>
<div class="clearfix"></div>
</div>
<% end %>
@@ -20,4 +20,4 @@
</div>
</div>
<%= render "comments/secondary_links" %>
<%= render "comments/secondary_links" %>

View File

@@ -1,6 +1,6 @@
<div class="comments-for-post" data-post-id="<%= post.id %>">
<% if show_header %>
<%= render :partial => "comments/partials/index/header", :locals => {:post => post} %>
<%= render "comments/partials/index/header", :post => post %>
<% end %>
<div class="list-of-comments">
@@ -15,6 +15,6 @@
<div class="new-comment">
<p><%= link_to "Post comment", new_comment_path, :class => "expand-comment-response" %></p>
<%= render :partial => "comments/partials/new/form", :locals => {:post => post} %>
<%= render "comments/partials/new/form", :post => post %>
</div>
</div>

View File

@@ -1,6 +1,7 @@
<div id="c-comments">
<div id="a-search">
<h1>Search Comments</h1>
<%= simple_form_for(@search) do |f| %>
<%= hidden_field_tag "group_by", "comment" %>
<%= f.input :body_matches, :label => "Body", :required => false %>

View File

@@ -1,2 +1,7 @@
<h1>Edit Message</h1>
<%= render :partial => "form", :locals => {:dmail => @dmail} %>
<div id="c-dmails">
<div id="a-edit">
<h1>Edit Message</h1>
<%= render "form", :dmail => @dmail %>
</div>
</div>

View File

@@ -1,15 +1,19 @@
<h1>Messages</h1>
<div id="c-dmails">
<div id="a-index">
<h1>Messages</h1>
<%= render "search" %>
<%= render "search" %>
<table>
<tbody>
<% @dmails.each do |dmail| %>
<% if params[:folder] == "sent" %>
<%= render :partial => "sent", :locals => {:dmail => dmail} %>
<% else %>
<%= render :partial => "received", :locals => {:dmail => dmail} %>
<% end %>
<% end %>
</tbody>
</table>
<table>
<tbody>
<% @dmails.each do |dmail| %>
<% if params[:folder] == "sent" %>
<%= render "sent", :dmail => dmail %>
<% else %>
<%= render "received", :dmail => dmail %>
<% end %>
<% end %>
</tbody>
</table>
</div>
</div>

View File

@@ -1,2 +1,7 @@
<h1>New Message</h1>
<%= render :partial => "form", :locals => {:dmail => @dmail} %>
<div id="c-dmails">
<div id="a-new">
<h1>New Message</h1>
<%= render "form", :dmail => @dmail %>
</div>
</div>

View File

@@ -1,8 +1,9 @@
<div class="dmails">
<div class="show">
<div class="c-dmails">
<div class="a-show">
<div class="dmail">
<h1><%= @dmail.title %></h1>
<%= format_text(@dmail.body) %>
<p>
<%= link_to "Respond", new_dmail_path(:respond_to_id => @dmail) %>
| <%= link_to "Forward", new_dmail_path(:respond_to_id => @dmail, :forward => true) %>

View File

@@ -1,6 +1,6 @@
<div id="c-explore-posts">
<div id="a-index">
<h1>Explore: <%= @post_set.min_date %> &ndash; <%= @post_set.max_date %></h1>
<h1>Explore: <%= @post_set.presenter.range_text %></h1>
<%= render "date_explore", :post_set => @post_set %>

View File

@@ -1,11 +1,11 @@
<div id="c-favorites">
<div id="a-index">
<aside id="sidebar">
<%= render :partial => "posts/partials/common/search", :locals => {:path => favorites_path, :tags => @favorite_set.tag_string} %>
<%= render "posts/partials/common/search", :path => favorites_path, :tags => @favorite_set.tag_string %>
<% if CurrentUser.is_privileged? %>
<section id="mode-box">
<%= render :partial => "posts/partials/index/mode_menu" %>
<%= render "posts/partials/index/mode_menu" %>
</section>
<% end %>
@@ -29,7 +29,7 @@
/fav:<%= CurrentUser.name %>
<% end %>
<%= render :partial => "posts/partials/common/secondary_links" %>
<%= render "posts/partials/common/secondary_links" %>
</div>
</div>

View File

@@ -1,6 +1,6 @@
<div class="list-of-forum-posts">
<% forum_posts.each do |forum_post| %>
<%= render :partial => "forum_posts/forum_post", :locals => {:forum_post => forum_post} %>
<%= render "forum_posts/forum_post", :forum_post => forum_post %>
<% end %>
</div>

View File

@@ -1,6 +1,6 @@
<div id="c-forum-topics">
<div id="a-show" class="single-forum-post list-of-forum-posts">
<%= render :partial => "forum_post", :locals => {:forum_post => @forum_post} %>
<%= render "forum_post", :forum_post => @forum_post %>
</div>
</div>

View File

@@ -1 +0,0 @@
<%= @forum_topic.presenter(@forum_posts).pagination_html(self) %>

View File

@@ -1,24 +1,34 @@
<h1>Forum</h1>
<div id="c-forum-topics">
<div id="a-index">
<h1>Forum</h1>
<table width="100%" class="striped">
<thead>
<tr>
<th>Title</th>
<th>Creator</th>
<th>Updated by</th>
<th>Updated at</th>
</tr>
</thead>
<tbody>
<% @forum_topics.each do |topic| %>
<tr>
<td><% if topic.is_sticky? %><span class="sticky">Sticky:</span> <% end %><%= link_to topic.title, forum_topic_path(topic) %></td>
<td><%= topic.creator.name %></td>
<td><%= topic.updater.name %></td>
<td><%= compact_time topic.updated_at %></td>
</tr>
<% end %>
</tbody>
</table>
<table width="100%" class="striped">
<thead>
<tr>
<th>Title</th>
<th>Creator</th>
<th>Updated by</th>
<th>Updated at</th>
</tr>
</thead>
<tbody>
<% @forum_topics.each do |topic| %>
<tr>
<td><% if topic.is_sticky? %><span class="sticky">Sticky:</span> <% end %><%= link_to topic.title, forum_topic_path(topic) %></td>
<td><%= topic.creator.name %></td>
<td><%= topic.updater.name %></td>
<td><%= compact_time topic.updated_at %></td>
</tr>
<% end %>
</tbody>
</table>
<%= numbered_paginator(@forum_topics) %>
</div>
</div>
<%= render "secondary_links" %>
<%= render "secondary_links" %>
<%= content_for(:html_header) do %>
<meta name="last-forum-read-at" content="<%= CurrentUser.last_forum_read_at.to_date %>">
<% end %>

View File

@@ -6,13 +6,14 @@
</div>
<% end %>
<%= render :partial => "forum_posts/listing", :locals => {:forum_posts => @forum_posts} %>
<%= render "paginator" %>
<%= render "forum_posts/listing", :forum_posts => @forum_posts %>
<%= numbered_paginator(@forum_posts) %>
</div>
</div>
<%= render "secondary_links" %>
<%= content_for(:page_title) do %>
forum/<%= @forum_topic.title %>
forum/<%= @forum_topic.title %>
<% end %>

View File

@@ -1,22 +1,27 @@
<h1>IP Bans</h1>
<div id="c-ip-bans">
<div id="a-index">
<h1>IP Bans</h1>
<table>
<thead>
<tr>
<th>IP Address</th>
<th>Banner</th>
<th>Reason</th>
<th></th>
</tr>
</thead>
<tbody>
<% @ip_bans.each do |ip_ban| %>
<tr>
<td><%= ip_ban.ip_addr %></td>
<td><%= ip_ban.creator.name %></td>
<td><%= ip_ban.reason %></td>
<td><%= link_to "Unban", ip_ban_path(ip_ban), :remote => true, :method => :delete, :confirm => "Do your really want to unban #{ip_ban.creator.name}?" %></td>
</tr>
<% end %>
</tbody>
</table>
</div>
</div>
<table>
<thead>
<tr>
<th>IP Address</th>
<th>Banner</th>
<th>Reason</th>
<th></th>
</tr>
</thead>
<tbody>
<% @ip_bans.each do |ip_ban| %>
<tr>
<td><%= ip_ban.ip_addr %></td>
<td><%= ip_ban.creator.name %></td>
<td><%= ip_ban.reason %></td>
<td><%= link_to "Unban", ip_ban_path(ip_ban), :remote => true, :method => :delete, :confirm => "Do your really want to unban #{ip_ban.creator.name}?" %></td>
</tr>
<% end %>
</tbody>
</table>

View File

@@ -1,7 +1,11 @@
<h1>New IP Ban</h1>
<div id="c-ip-bans">
<div id="a-new">
<h1>New IP Ban</h1>
<%= simple_form_for(@ip_ban) do |f| %>
<%= f.input :ip_addr %>
<%= f.input :reason %>
<%= f.button :submit %>
<% end %>
<%= simple_form_for(@ip_ban) do |f| %>
<%= f.input :ip_addr %>
<%= f.input :reason %>
<%= f.button :submit %>
<% end %>
</div>
</div>

View File

@@ -1,23 +1,27 @@
<h1>Janitor Trials</h1>
<div id="c-janitor-trials">
<div id="a-index">
<h1>Janitor Trials</h1>
<table>
<thead>
<tr>
<th>User</th>
<th>Duration</th>
<td></td>
</tr>
</thead>
<tbody>
<% @janitor_trials.each do |janitor_trial| %>
<tr>
<td><%= janitor_trial.user.name %></td>
<td><%= janitor_trial.created_at %></td>
<td>
<%= link_to "Promote", promote_janitor_trial_path(janitor_trial), :remote => true, :method => :put %>
| <%= link_to "Demote", demote_janitor_trial_path(janitor_trial), :remote => true, :method => :put %>
</td>
</tr>
<% end %>
</tbody>
</table>
<table>
<thead>
<tr>
<th>User</th>
<th>Duration</th>
<td></td>
</tr>
</thead>
<tbody>
<% @janitor_trials.each do |janitor_trial| %>
<tr>
<td><%= janitor_trial.user.name %></td>
<td><%= janitor_trial.created_at %></td>
<td>
<%= link_to "Promote", promote_janitor_trial_path(janitor_trial), :remote => true, :method => :put %>
| <%= link_to "Demote", demote_janitor_trial_path(janitor_trial), :remote => true, :method => :put %>
</td>
</tr>
<% end %>
</tbody>
</table>
</div>
</div>

View File

@@ -1,6 +1,10 @@
<h1>New Janitor Trial</h1>
<div id="c-janitor-trials">
<div id="a-new">
<h1>New Janitor Trial</h1>
<%= simple_form_for(@janitor_trial) do |f| %>
<%= f.input :user_id %>
<%= f.button :submit %>
<% end %>
<%= simple_form_for(@janitor_trial) do |f| %>
<%= f.input :user_id %>
<%= f.button :submit %>
<% end %>
</div>
</div>

View File

@@ -38,4 +38,4 @@
</div>
</div>
<%= render :partial => "posts/partials/common/secondary_links" %>
<%= render "posts/partials/common/secondary_links" %>

View File

@@ -1,4 +1,4 @@
<div id="news-ticker">
<div id="news-ticker" data-updated-at="2011-09-01">
<ul>
</ul>

View File

@@ -35,7 +35,7 @@
<%= sequential_paginator(@note_versions) %>
<%= render :partial => "notes/secondary_links" %>
<%= render "notes/secondary_links" %>
</div>
</div>

View File

@@ -17,4 +17,4 @@
</div>
</div>
<%= render :partial => "pools/secondary_links" %>
<%= render "pools/secondary_links" %>

View File

@@ -37,4 +37,4 @@
</div>
</div>
<%= render :partial => "pools/secondary_links" %>
<%= render "pools/secondary_links" %>

View File

@@ -1,17 +1,21 @@
<p>If this post was automatically deleted, <strong>then it means at least ten janitors all thought it didn't belong on the site</strong>. If you still believe this image was wrongfully deleted, then you can appeal its deletion.</p>
<div id="c-post-appeals">
<div id="a-index">
<p>If this post was automatically deleted, <strong>then it means at least ten janitors all thought it didn't belong on the site</strong>. If you still believe this image was wrongfully deleted, then you can appeal its deletion.</p>
<p>Some valid reasons for appealing include:</p>
<p>Some valid reasons for appealing include:</p>
<ul>
<li>Funny</li>
<li>Weird</li>
<li>Translated</li>
<li>Part of a pool</li>
</ul>
<ul>
<li>Funny</li>
<li>Weird</li>
<li>Translated</li>
<li>Part of a pool</li>
</ul>
<p>All users are limited to 5 appeals a day. For more details, please read the <%= link_to "wiki", wiki_pages_path(:title => "help:deletion_appeals") %>.</p>
<p>All users are limited to 5 appeals a day. For more details, please read the <%= link_to "wiki", wiki_pages_path(:title => "help:deletion_appeals") %>.</p>
<%= simple_form_for(@post_appeal, :remote => true, :format => :js) do |f| %>
<%= hidden_field_tag "post_appeal[post_id]", @post_appeal.post_id %>
<%= f.text_field :reason, :size => "40x5" %>
<% end %>
<%= simple_form_for(@post_appeal, :remote => true, :format => :js) do |f| %>
<%= hidden_field_tag "post_appeal[post_id]", @post_appeal.post_id %>
<%= f.text_field :reason, :size => "40x5" %>
<% end %>
</div>
</div>

View File

@@ -1,25 +1,29 @@
<p>If you believe a post does not belong on this site, you can flag for its deletion. As a reminder, the following are some common reasons for flagging a post:</p>
<div id="c-post-flags">
<div id="a-index">
<p>If you believe a post does not belong on this site, you can flag for its deletion. As a reminder, the following are some common reasons for flagging a post:</p>
<ul>
<li>Not anime-related</li>
<li>Furry: a character has body fur or an animal face</li>
<li>Watermark: text or logo inserted by someone besides the original artist</li>
<li>Poor compression: JPEG artifacts</li>
<li>Guro: mutilation, extreme bodily distension</li>
<li>Bad proportions: extremely large breasts or penises</li>
<li>Manga: Multiple pages of a manga, doujinshi, or comic that don't stand up to individual scrutiny</li>
<li>Fake translations: Made up translations are banned</li>
</ul>
<ul>
<li>Not anime-related</li>
<li>Furry: a character has body fur or an animal face</li>
<li>Watermark: text or logo inserted by someone besides the original artist</li>
<li>Poor compression: JPEG artifacts</li>
<li>Guro: mutilation, extreme bodily distension</li>
<li>Bad proportions: extremely large breasts or penises</li>
<li>Manga: Multiple pages of a manga, doujinshi, or comic that don't stand up to individual scrutiny</li>
<li>Fake translations: Made up translations are banned</li>
</ul>
<p>The following are <strong>NOT</strong> valid reasons for flagging a post:</p>
<p>The following are <strong>NOT</strong> valid reasons for flagging a post:</p>
<ul>
<li>Duplicate: just parent to the original</li>
</ul>
<ul>
<li>Duplicate: just parent to the original</li>
</ul>
<p>Enter a reason:</p>
<p>Enter a reason:</p>
<%= simple_form_for(@post_flag, :remote => true, :format => :js) do |f| %>
<%= f.input :post_id, :as => :hidden %>
<%= f.text_field :reason %>
<% end %>
<%= simple_form_for(@post_flag, :remote => true, :format => :js) do |f| %>
<%= f.input :post_id, :as => :hidden %>
<%= f.text_field :reason %>
<% end %>
</div>
</div>

View File

@@ -11,7 +11,7 @@
<% if @post_versions.empty? %>
<%= render "post_sets/blank" %>
<% else %>
<%= render :partial => "listing", :locals => {:post_versions => @post_versions} %>
<%= render"listing", :post_versions => @post_versions %>
<% end %>
</div>
</div>

View File

@@ -1,28 +1,28 @@
<div id="c-posts">
<div id="a-index">
<aside id="sidebar">
<%= render :partial => "posts/partials/common/search", :locals => {:path => posts_path, :tags => params[:tags]} %>
<%= render "posts/partials/common/search", :path => posts_path, :tags => params[:tags] %>
<%= render :partial => "posts/partials/index/mode_menu" %>
<%= render "posts/partials/index/mode_menu" %>
<section id="tag-box">
<h1>Tags</h1>
<%= @post_set.presenter.tag_list_html(self) %>
</section>
<%= render :partial => "posts/partials/index/blacklist" %>
<%= render "posts/partials/index/blacklist" %>
</aside>
<section id="content">
<%= render :partial => "wiki_pages/excerpt", :locals => {:post_set => @post_set} %>
<%= render :partial => "posts/partials/index/posts", :locals => {:post_set => @post_set} %>
<%= render "wiki_pages/excerpt", :post_set => @post_set %>
<%= render "posts/partials/index/posts", :post_set => @post_set %>
</section>
<% content_for(:page_title) do %>
/<%= @post_set.tag_string %>
<% end %>
<%= render :partial => "posts/partials/common/secondary_links" %>
<%= render "posts/partials/common/secondary_links" %>
</div>
</div>

View File

@@ -16,9 +16,6 @@
<option value="lock-note">Lock notes</option>
<option value="edit-tag-script">Edit tag script</option>
<option value="apply-tag-script">Apply tag script</option>
<% if CurrentUser.user.is_janitor? %>
<option value="approve">Approve</option>
<% end %>
</select>
</form>
</section>

View File

@@ -1,12 +1,12 @@
<div id="c-posts">
<div id="a-show">
<aside id="sidebar">
<%= render :partial => "posts/partials/common/search", :locals => {:path => posts_path, :tags => params[:tags]} %>
<%= render "posts/partials/common/search", :path => posts_path, :tags => params[:tags] %>
<% if @post.pools.any? %>
<section id="pool-sidebar">
<h1>Pools</h1>
<%= render :partial => "posts/partials/show/pools", :locals => {:post => @post} %>
<%= render "posts/partials/show/pools", :post => @post %>
</section>
<% end %>
@@ -17,12 +17,12 @@
<section>
<h1>Information</h1>
<%= render :partial => "posts/partials/show/information", :locals => {:post => @post} %>
<%= render "posts/partials/show/information", :post => @post %>
</section>
<section>
<h1>Options</h1>
<%= render :partial => "posts/partials/show/options", :locals => {:post => @post} %>
<%= render "posts/partials/show/options", :post => @post %>
</section>
<section>
@@ -36,7 +36,7 @@
</aside>
<section id="content">
<%= render :partial => "posts/partials/show/notices", :locals => {:post => @post} %>
<%= render "posts/partials/show/notices", :post => @post %>
<section id="image-container">
<div id="note-container"></div>
@@ -50,7 +50,7 @@
</menu>
<section id="comments">
<%= render :partial => "comments/partials/index/list", :locals => {:comments => @post.comments, :post => @post, :show_header => false} %>
<%= render "comments/partials/index/list", :comments => @post.comments, :post => @post, :show_header => false %>
</section>
<section id="notes">
@@ -62,7 +62,7 @@
</section>
<section id="edit">
<%= render :partial => "posts/partials/show/edit", :locals => {:post => @post} %>
<%= render "posts/partials/show/edit", :post => @post %>
</section>
</section>
</div>
@@ -93,4 +93,4 @@
<meta name="post-is-deleted" content="<%= @post.is_deleted? %>">
<% end %>
<%= render :partial => "posts/partials/common/secondary_links" %>
<%= render "posts/partials/common/secondary_links" %>

View File

@@ -1,66 +0,0 @@
<h4>Report: <%= @report_title %></h4>
<div>
<div style="margin-bottom: 1em;">
<% form_tag({:action => params[:action]}, :method => :get) do %>
<table width="100%">
<tfoot>
<tr>
<td colspan="2"><%= submit_tag "Search" %></td>
</tr>
</tfoot>
<tbody>
<tr>
<th width="15%"><label for="start_date">Start Date</label></th>
<td width="85%"><%= text_field_tag "start_date", @start_date, :size => 10 %></td>
</tr>
<tr>
<th><label for="end_date">End Date</label></th>
<td><%= text_field_tag "end_date", @end_date, :size => 10 %></td>
</tr>
<tr>
<th><label for="limit">Limit</label></th>
<td><%= text_field_tag "limit", @limit, :size => 5 %></td>
</tr>
<tr>
<td><label for="level">Level</label></td>
<td><%= user_level_select_tag "level", :include_blank => true %></td>
</tr>
</tbody>
</table>
<% end %>
</div>
<div>
<table width="100%" class="highlightable">
<thead>
<tr>
<th width="15%">User</th>
<th width="10%">Changes</th>
<th width="75%">Percentage</th>
</tr>
</thead>
<tfoot>
<td>Total</td>
<td><%= @users[0]["sum"].to_i %></td>
<td></td>
</tfoot>
<tbody>
<% @users.each do |user| %>
<tr class="<%= cycle 'even', 'odd' %>">
<td><%= link_to_unless user["id"].nil?, h(user["name"]), :controller => "user", :action => "show", :id => user["id"] %></td>
<td><%= link_to_unless user["id"].nil?, user["change_count"], @change_params.call(user["id"]) %></td>
<td><%= number_to_percentage 100 * user["change_count"] / user["sum"], :precision => 1 %></td>
</tr>
<% end %>
</tbody>
</table>
</div>
</div>
<% content_for("subnavbar") do %>
<li><%= link_to "Tags", :action => "tag_updates", :start_date => @start_date, :end_date => @end_date %></li>
<li><%= link_to "Notes", :action => "note_updates", :start_date => @start_date, :end_date => @end_date %></li>
<li><%= link_to "Wiki", :action => "wiki_updates", :start_date => @start_date, :end_date => @end_date %></li>
<li><%= link_to "Uploads", :action => "post_uploads", :start_date => @start_date, :end_date => @end_date %></li>
<% end %>

View File

@@ -1,40 +0,0 @@
<script language="javascript" type="text/javascript" src="/javascripts/flotr-0.2.0-alpha.js"></script>
<% form_tag({:action => "tag_history"}, :method => :get) do %>
<table width="100%">
<tbody>
<tr>
<th width="10%">Tags</th>
<td width="90%"><%= text_field_tag "tag", params[:tag], :size => 50 %></td>
</tr>
<tr>
<th>Start Date</th>
<td><%= text_field_tag "start_date", @start_date %></td>
</tr>
<tr>
<th>End Date</th>
<td><%= text_field_tag "end_date", @end_date %></td>
</tr>
<tr>
<td colspan="2"><%= submit_tag "Search" %></td>
</tr>
</tbody>
</table>
<% end %>
<div id="container" style="width: 100%; height: 400px"></div>
<% if @counts %>
<script type="text/javascript" charset="utf-8">
Flotr.draw(
$("container"), [<%= @counts.map {|x| "{data: #{x[1].to_json}, label: #{x[0].to_json}}"}.join(", ") %>],
{
lines: {show: true},
xaxis: {ticks: <%= @ticks.to_json %>},
yaxis: {noTicks: 10, tickDecimals: 0},
legend: {show: true},
shadowSize: 0
}
)
</script>
<% end %>

View File

@@ -1,5 +1,5 @@
<div id="sessions">
<div id="new">
<div id="c-sessions">
<div id="a-new">
<section>
<h1>Login</h1>
<%= form_tag(session_path, :class => "simple_form") do %>

View File

@@ -1,11 +1,11 @@
<div id="c-tag-subscriptions">
<div id="a-posts">
<aside id="sidebar">
<%= render :partial => "posts/partials/common/search", :locals => {:path => posts_tag_subscription_path, :tags => @post_set.tag_string} %>
<%= render "posts/partials/common/search", :path => posts_tag_subscription_path, :tags => @post_set.tag_string %>
<%= render :partial => "posts/partials/index/mode_menu" %>
<%= render "posts/partials/index/mode_menu" %>
<%= render :partial => "posts/partials/index/blacklist" %>
<%= render "posts/partials/index/blacklist" %>
</aside>
<section id="content">
@@ -20,7 +20,7 @@
/fav:<%= CurrentUser.name %>
<% end %>
<%= render :partial => "posts/partials/common/secondary_links" %>
<%= render "posts/partials/common/secondary_links" %>
</div>
</div>

View File

@@ -27,4 +27,4 @@
</div>
</div>
<%= render :partial => "posts/partials/common/secondary_links" %>
<%= render "posts/partials/common/secondary_links" %>

View File

@@ -59,4 +59,4 @@
/ Upload
<% end %>
<%= render :partial => "posts/partials/common/secondary_links" %>
<%= render "posts/partials/common/secondary_links" %>

View File

@@ -10,6 +10,8 @@
<p>This upload has finished processing. <%= link_to "View the post", post_path(@upload.post_id) %>.</p>
<% elsif @upload.is_pending? %>
<p>This upload is waiting to be processed. Please wait a few seconds.</p>
<% elsif @upload.is_processing? %>
<p>This upload is being processed. Please wait a few seconds.</p>
<% else %>
<p>An error occurred: <%= @upload.status %></p>
<% end %>
@@ -21,4 +23,4 @@
<% end %>
</p>
<%= render :partial => "posts/partials/common/secondary_links" %>
<%= render "posts/partials/common/secondary_links" %>

View File

@@ -1,3 +1,54 @@
<h1>Namasté <%= CurrentUser.pretty_name %>!</h1>
<div id="c-users">
<div id="a-show">
<h1>Show User: <%= CurrentUser.pretty_name %></h1>
<%= render :partial => "secondary_links" %>
<dl>
<dt>Join Date</dt>
<dd><%= @presenter.join_date %></dd>
<dt>Inviter</dt>
<dd><%= @presenter.inviter(self) %></dd>
<dt>Level</dt>
<dd><%= @presenter.level %></dd>
<dt>Upload Limit</dt>
<dd><%= @presenter.upload_limit %></dd>
<dt>Uploads</dt>
<dd><%= @presenter.uploads(self) %></dd>
<dt>Deleted Uploads</dt>
<dd><%= @presenter.deleted_uploads(self) %></dd>
<dt>Favorites</dt>
<dd><%= @presenter.favorites(self) %></dd>
<dt>Subscriptions</dt>
<dd><%= @presenter.subscriptions(self) %></dd>
<dt>Post Changes</dt>
<dd><%= @presenter.post_versions(self) %></dd>
<dt>Note Changes</dt>
<dd><%= @presenter.note_versions(self) %></dd>
<dt>Wiki Page Changes</dt>
<dd><%= @presenter.wiki_page_versions(self) %></dd>
<dt>Pool Changes</dt>
<dd><%= @presenter.pool_versions(self) %></dd>
<dt>Forum Posts</dt>
<dd><%= @presenter.forum_posts(self) %></dd>
<dt>Approvals</dt>
<dd><%= @presenter.approvals(self) %></dd>
<dt>Feedback</dt>
<dd><%= @presenter.feedbacks(self) %></dd>
</dl>
</div>
</div>
<%= render "secondary_links" %>

View File

@@ -1,6 +1,6 @@
<div id="c-wiki-pages">
<div id="a-index">
<%= render :partial => "wiki_pages/sidebar" %>
<%= render "wiki_pages/sidebar" %>
<section id="content">
<h1>Wiki Pages</h1>
@@ -37,4 +37,4 @@
</div>
</div>
<%= render :partial => "wiki_pages/secondary_links" %>
<%= render "wiki_pages/secondary_links" %>

View File

@@ -1,6 +1,6 @@
<div id="c-wiki-pages">
<div id="a-index">
<%= render :partial => "sidebar" %>
<%= render "sidebar" %>
<section id="content">
<h1>Wiki Pages</h1>

View File

@@ -72,6 +72,11 @@ module Danbooru
300
end
# If a solid state drive is availble, cache the thumbnails on the SSD to reduce disk seek times.
def ssd_path
nil
end
# List of memcached servers
def memcached_servers
%w(localhost:11211)

View File

@@ -1,39 +0,0 @@
module Danbooru
class CustomConfiguration < Configuration
# Define your custom overloads here
def app_name
"Lorem"
end
def posts_per_page
3
end
def is_user_restricted?(user)
!user.is_privileged? || user.name == "ppayne"
end
def is_post_restricted?(post)
post.has_tag?("loli") || post.has_tag?("shota")
end
def custom_html_header_content
%{
<script type="text/javascript">
//var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
//document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try {
//var pageTracker = _gat._getTracker("UA-86094-4");
//pageTracker._trackPageview();
} catch(err) {}
</script>
}.html_safe
end
def is_user_advertiser?(user)
user.is_admin? || user.name == "ppayne"
end
end
end

118
config/deploy.rb Normal file
View File

@@ -0,0 +1,118 @@
$:.unshift(File.expand_path("./lib", ENV["rvm_path"]))
set :rvm_ruby_string, "ruby-1.9.2"
set :rvm_bin_path, "/usr/local/rvm/bin"
require 'rvm/capistrano'
set :stages, %w(production staging)
set :default_stage, "staging"
require 'capistrano/ext/multistage'
require 'bundler/capistrano'
set :whenever_command, "bundle exec whenever"
set :whenever_environment, defer {stage}
require 'whenever/capistrano'
set :application, "danbooru"
set :repository, "git://github.com/r888888888/danbooru.git"
set :scm, :git
set :user, "danbooru"
set :deploy_to, "/var/www/#{application}"
default_run_options[:pty] = true
namespace :local_config do
desc "Create the shared config directory"
task :setup_shared_directory do
run "mkdir -p #{deploy_to}/shared/config"
end
desc "Initialize local config files"
task :setup_local_files do
run "curl -s https://raw.github.com/r888888888/danbooru/master/script/install/danbooru_local_config.rb.templ > #{deploy_to}/shared/config/danbooru_local_config.rb"
run "curl -s https://raw.github.com/r888888888/danbooru/master/script/install/database.yml.templ > #{deploy_to}/shared/config/database.yml"
end
desc "Link the local config files"
task :link_local_files do
run "ln -s #{deploy_to}/shared/config/danbooru_local_config.rb #{release_path}/config/danbooru_local_config.rb"
run "ln -s #{deploy_to}/shared/config/database.yml #{release_path}/config/database.yml"
end
end
namespace :data do
task :setup_directories do
run "mkdir -p #{deploy_to}/shared/data"
run "mkdir #{deploy_to}/shared/data/preview"
run "mkdir #{deploy_to}/shared/data/small"
run "mkdir #{deploy_to}/shared/data/large"
run "mkdir #{deploy_to}/shared/data/original"
end
task :link_directories do
run "rm -f #{release_path}/public/data"
run "ln -s #{deploy_to}/shared/data #{release_path}/public/data"
end
end
desc "Change ownership of common directory to user"
task :reset_ownership_of_common_directory do
sudo "chown -R #{user}:#{user} /var/www/danbooru"
end
namespace :deploy do
namespace :web do
desc "Present a maintenance page to visitors."
task :disable do
maintenance_html_path = "#{current_path}/public/maintenance.html.bak"
run "if [ -e #{maintenance_html_path} ] ; then mv #{maintenance_html_path} #{current_path}/public/maintenance.html ; fi"
end
desc "Makes the application web-accessible again."
task :enable do
maintenance_html_path = "#{current_path}/public/maintenance.html"
run "if [ -e #{maintenance_html_path} ] ; then mv #{maintenance_html_path} #{current_path}/public/maintenance.html.bak ; fi"
end
end
desc "Restart the application"
task :restart do
run "touch #{current_path}/tmp/restart.txt"
end
desc "Compile the image resizer"
task :compile_image_resizer do
run "cd #{release_path}/lib/danbooru_image_resizer ; ruby extconf.rb ; make"
end
end
namespace :delayed_job do
desc "Start delayed_job process"
task :start, :roles => :app do
run "cd #{current_path}; RAILS_ENV=#{rails_env} script/delayed_job start"
end
desc "Stop delayed_job process"
task :stop, :roles => :app do
run "cd #{current_path}; RAILS_ENV=#{rails_env} script/delayed_job stop"
end
desc "Restart delayed_job process"
task :restart, :roles => :app do
run "cd #{current_path}; RAILS_ENV=#{rails_env} script/delayed_job restart"
end
end
after "deploy:setup", "reset_ownership_of_common_directory"
after "deploy:setup", "local_config:setup_shared_directory"
after "deploy:setup", "local_config:setup_local_files"
after "deploy:setup", "data:setup_directories"
after "deploy:symlink", "local_config:link_local_files"
after "deploy:symlink", "data:link_directories"
after "deploy:symlink", "deploy:compile_image_resizer"
after "deploy:start", "delayed_job:start"
after "deploy:stop", "delayed_job:stop"
after "deploy:restart", "delayed_job:restart"
before "deploy:update", "deploy:web:disable"
after "deploy:restart", "deploy:web:enable"

View File

@@ -0,0 +1,2 @@
server "sonohara.donmai.us", :web, :app, :primary => true
server "hijiribe.donmai.us", :web, :app

Some files were not shown because too many files have changed in this diff Show More