Merge branch 'master' into skylight
This commit is contained in:
commit
31e086de0e
2
.buildpacks
Normal file
2
.buildpacks
Normal file
|
@ -0,0 +1,2 @@
|
|||
https://github.com/Scalingo/nodejs-buildpack
|
||||
https://github.com/Scalingo/ruby-buildpack
|
2
.slugignore
Normal file
2
.slugignore
Normal file
|
@ -0,0 +1,2 @@
|
|||
node_modules/
|
||||
.cache/
|
|
@ -117,6 +117,12 @@ Which will re-create the updated containers, leaving databases and data as is. D
|
|||
|
||||
Docker is great for quickly trying out software, but it has its drawbacks too. If you prefer to run Mastodon without using Docker, refer to the [production guide](docs/Running-Mastodon/Production-guide.md) for examples, configuration and instructions.
|
||||
|
||||
## Deployment on Scalingo
|
||||
|
||||
[![Deploy on Scalingo](https://cdn.scalingo.com/deploy/button.svg)](https://my.scalingo.com/deploy?source=https://github.com/tootsuite/mastodon#master)
|
||||
|
||||
[You can view a guide for deployment on Scalingo here.](docs/Running-Mastodon/Scalingo-guide.md)
|
||||
|
||||
## Deployment on Heroku (experimental)
|
||||
|
||||
[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy)
|
||||
|
|
|
@ -34,12 +34,7 @@ class FeedManager
|
|||
trim(timeline_type, account.id)
|
||||
end
|
||||
|
||||
broadcast(account.id, event: 'update', payload: inline_render(account, 'api/v1/statuses/show', status))
|
||||
end
|
||||
|
||||
def broadcast(timeline_id, options = {})
|
||||
options[:queued_at] = (Time.now.to_f * 1000.0).to_i
|
||||
redis.publish("timeline:#{timeline_id}", Oj.dump(options))
|
||||
PushUpdateWorker.perform_async(account.id, status.id)
|
||||
end
|
||||
|
||||
def trim(type, account_id)
|
||||
|
@ -81,10 +76,6 @@ class FeedManager
|
|||
end
|
||||
end
|
||||
|
||||
def inline_render(target_account, template, object)
|
||||
Rabl::Renderer.new(template, object, view_path: 'app/views', format: :json, scope: InlineRablScope.new(target_account)).render
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def redis
|
||||
|
|
13
app/lib/inline_renderer.rb
Normal file
13
app/lib/inline_renderer.rb
Normal file
|
@ -0,0 +1,13 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class InlineRenderer
|
||||
def self.render(status, current_account, template)
|
||||
Rabl::Renderer.new(
|
||||
template,
|
||||
status,
|
||||
view_path: 'app/views',
|
||||
format: :json,
|
||||
scope: InlineRablScope.new(current_account)
|
||||
).render
|
||||
end
|
||||
end
|
|
@ -50,22 +50,22 @@ class FanOutOnWriteService < BaseService
|
|||
end
|
||||
|
||||
def render_anonymous_payload(status)
|
||||
@payload = FeedManager.instance.inline_render(nil, 'api/v1/statuses/show', status)
|
||||
@payload = InlineRenderer.render(status, nil, 'api/v1/statuses/show')
|
||||
end
|
||||
|
||||
def deliver_to_hashtags(status)
|
||||
Rails.logger.debug "Delivering status #{status.id} to hashtags"
|
||||
|
||||
status.tags.pluck(:name).each do |hashtag|
|
||||
FeedManager.instance.broadcast("hashtag:#{hashtag}", event: 'update', payload: @payload)
|
||||
FeedManager.instance.broadcast("hashtag:#{hashtag}:local", event: 'update', payload: @payload) if status.account.local?
|
||||
Redis.current.publish("hashtag:#{hashtag}", Oj.dump(event: :update, payload: @payload))
|
||||
Redis.current.publish("hashtag:#{hashtag}:local", Oj.dump(event: :update, payload: @payload)) if status.account.local?
|
||||
end
|
||||
end
|
||||
|
||||
def deliver_to_public(status)
|
||||
Rails.logger.debug "Delivering status #{status.id} to public timeline"
|
||||
|
||||
FeedManager.instance.broadcast(:public, event: 'update', payload: @payload)
|
||||
FeedManager.instance.broadcast('public:local', event: 'update', payload: @payload) if status.account.local?
|
||||
Redis.current.publish('public', Oj.dump(event: 'update', payload: @payload))
|
||||
Redis.current.publish('public:local', Oj.dump(event: 'update', payload: @payload)) if status.account.local?
|
||||
end
|
||||
end
|
||||
|
|
|
@ -50,7 +50,7 @@ class NotifyService < BaseService
|
|||
def create_notification
|
||||
@notification.save!
|
||||
return unless @notification.browserable?
|
||||
FeedManager.instance.broadcast(@recipient.id, event: 'notification', payload: FeedManager.instance.inline_render(@recipient, 'api/v1/notifications/show', @notification))
|
||||
Redis.current.publish(@recipient.id, Oj.dump(event: :notification, payload: InlineRenderer.render(@notification, @recipient, 'api/v1/notifications/show')))
|
||||
end
|
||||
|
||||
def send_email
|
||||
|
|
|
@ -65,17 +65,17 @@ class RemoveStatusService < BaseService
|
|||
redis.zremrangebyscore(FeedManager.instance.key(type, receiver.id), status.id, status.id)
|
||||
end
|
||||
|
||||
FeedManager.instance.broadcast(receiver.id, event: 'delete', payload: status.id)
|
||||
Redis.current.publish(receiver.id, Oj.dump(event: :delete, payload: status.id))
|
||||
end
|
||||
|
||||
def remove_from_hashtags(status)
|
||||
status.tags.each do |tag|
|
||||
FeedManager.instance.broadcast("hashtag:#{tag.name}", event: 'delete', payload: status.id)
|
||||
Redis.current.publish("hashtag:#{tag.name}", Oj.dump(event: :delete, payload: status.id))
|
||||
end
|
||||
end
|
||||
|
||||
def remove_from_public(status)
|
||||
FeedManager.instance.broadcast(:public, event: 'delete', payload: status.id)
|
||||
Redis.current.publish('public', Oj.dump(event: :delete, payload: status.id))
|
||||
end
|
||||
|
||||
def redis
|
||||
|
|
15
app/workers/push_update_worker.rb
Normal file
15
app/workers/push_update_worker.rb
Normal file
|
@ -0,0 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class PushUpdateWorker
|
||||
include Sidekiq::Worker
|
||||
|
||||
def perform(account_id, status_id)
|
||||
account = Account.find(account_id)
|
||||
status = Status.find(status_id)
|
||||
message = InlineRenderer.render(status, account, 'api/v1/statuses/show')
|
||||
|
||||
Redis.current.publish("timeline:#{account.id}", Oj.dump(event: :update, payload: message, queued_at: (Time.now.to_f * 1000.0).to_i))
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
true
|
||||
end
|
||||
end
|
|
@ -1,4 +1,5 @@
|
|||
Rabl.configure do |config|
|
||||
config.json_engine = Oj
|
||||
config.cache_all_output = false
|
||||
config.cache_sources = Rails.env.production?
|
||||
config.include_json_root = false
|
||||
|
|
|
@ -21,12 +21,12 @@ fi:
|
|||
features_headline: Mikä erottaa Mastodonin muista
|
||||
get_started: Aloita käyttö
|
||||
links: Linkit
|
||||
other_instances: Muut palvelimet
|
||||
other_instances: muuhun palvelimeen
|
||||
source_code: Lähdekoodi
|
||||
status_count_after: statukset
|
||||
status_count_before: Kuka loi
|
||||
status_count_after: statusta
|
||||
status_count_before: Ovat luoneet
|
||||
terms: Ehdot
|
||||
user_count_after: käyttäjät
|
||||
user_count_after: käyttäjää
|
||||
user_count_before: Koti käyttäjälle
|
||||
accounts:
|
||||
follow: Seuraa
|
||||
|
@ -89,7 +89,7 @@ fi:
|
|||
preface: Voit tuoda tiettyä dataa kaikista ihmisistä joita seuraat tai estät tilillesi tälle palvelimelle tiedostoista, jotka on luotu toisella palvelimella
|
||||
success: Datasi on onnistuneesti ladattu ja käsitellään pian
|
||||
types:
|
||||
blocking: Esto lista
|
||||
blocking: Estetyt lista
|
||||
following: Seuratut lista
|
||||
upload: Lähetä
|
||||
landing_strip_html: <strong>%{name}</strong> on käyttäjä domainilla <strong>%{domain}</strong>. Voit seurata tai vuorovaikuttaa heidän kanssaan jos sinulla on tili yleisessä verkossa. Jos sinulla ei ole tiliä, voit <a href="%{sign_up_path}">rekisteröityä täällä</a>.
|
||||
|
@ -132,7 +132,7 @@ fi:
|
|||
edit_profile: Muokkaa profiilia
|
||||
export: Datan vienti
|
||||
import: Datan tuonti
|
||||
preferences: Mieltymykset
|
||||
preferences: Ominaisuudet
|
||||
settings: Asetukset
|
||||
two_factor_auth: Kaksivaiheinen tunnistus
|
||||
statuses:
|
||||
|
@ -154,7 +154,7 @@ fi:
|
|||
description_html: Jos otat käyttöön <strong>kaksivaiheisen tunnistuksen</stron>, kirjautumiseen vaaditaan puhelin, joka voi generoida tokeneita kirjautumista varten.
|
||||
disable: Poista käytöstä
|
||||
enable: Ota käyttöön
|
||||
instructions_html: "<strong>Skannaa tämä QR-koodi Google Authenticator tai samanlaiseen sovellukseen puhelimellasi</strong>. Tästä hetkestä lähtien, ohjelma generoi tokenit mikä sinun tarvitsee syöttää sisäänkirjautuessa."
|
||||
instructions_html: "<strong>Skannaa tämä QR-koodi Google Authenticator tai samanlaiseen sovellukseen puhelimellasi</strong>. Tästä hetkestä lähtien ohjelma generoi koodin, mikä sinun tarvitsee syöttää sisäänkirjautuessa."
|
||||
plaintext_secret_html: 'Plain-text secret: <samp>%{secret}</samp>'
|
||||
warning: Jos et juuri nyt voi konfiguroida authenticator-applikaatiota juuri nyt, sinun pitäisi klikata "Poista käytöstä" tai et voi kirjautua sisään.
|
||||
users:
|
||||
|
|
|
@ -88,8 +88,9 @@ It is recommended to create a special user for mastodon on the server (you could
|
|||
|
||||
## General dependencies
|
||||
|
||||
sudo apt-get install imagemagick ffmpeg libpq-dev libxml2-dev libxslt1-dev nodejs file git curl
|
||||
curl -sL https://deb.nodesource.com/setup_4.x | sudo bash -
|
||||
sudo apt-get install imagemagick ffmpeg libpq-dev libxml2-dev libxslt1-dev nodejs file
|
||||
apt-get intall nodejs
|
||||
sudo npm install -g yarn
|
||||
|
||||
## Redis
|
||||
|
|
13
docs/Running-Mastodon/Scalingo-guide.md
Normal file
13
docs/Running-Mastodon/Scalingo-guide.md
Normal file
|
@ -0,0 +1,13 @@
|
|||
Scalingo guide
|
||||
==============
|
||||
|
||||
[![Deploy on Scalingo](https://cdn.scalingo.com/deploy/button.svg)](https://my.scalingo.com/deploy?source=https://github.com/tootsuite/mastodon#master)
|
||||
|
||||
1. Click the above button.
|
||||
2. Fill in the options requested.
|
||||
* You can use a .scalingo.io domain, which will be simple to set up, or you can use a custom domain.
|
||||
* You will want Amazon S3 for file storage. The only exception is for development purposes, where you may not care if files are not saved. Follow a guide online for creating a free Amazon S3 bucket and Access Key, then enter the details.
|
||||
* If you want your Mastodon to be able to send emails, configure SMTP settings here (or later). Consider using [Mailgun](https://mailgun.com) or similar, who offer free plans that should suit your interests.
|
||||
3. Deploy! The app should be set up, with a working web interface and database. You can change settings and manage versions from the Heroku dashboard.
|
||||
|
||||
You may need to use the `scalingo` CLI application to run `USERNAME=yourUsername rails mastodon:make_admin` to make yourself an admin.
|
|
@ -20,14 +20,15 @@ There is also a list at [instances.mastodon.xyz](https://instances.mastodon.xyz)
|
|||
| [social.diskseven.com](https://social.diskseven.com) |Single user|No|Yes|
|
||||
| [social.gestaltzerfall.net](https://social.gestaltzerfall.net) |Single user|No|No|
|
||||
| [mastodon.xyz](https://mastodon.xyz) |N/A|Yes|Yes|
|
||||
| [mastodon.partipirate.org](https://mastodon.partipirate.org) |French Pirate Part Instance - Politics and stuff|Yes|No|
|
||||
| [mastodon.partipirate.org](https://mastodon.partipirate.org) |French Pirate Party Instance - Politics and stuff|Yes|No|
|
||||
| [social.targaryen.house](https://social.targaryen.house) |Federates everywhere, quick updates.|Yes|Yes|
|
||||
| [masto.themimitoof.fr](https://masto.themimitoof.fr) |N/A|Yes|Yes|
|
||||
| [mstdn.io](https://mstdn.io) |N/A|Yes|Yes|
|
||||
| [social.imirhil.fr](https://social.imirhil.fr) |N/A|No|Yes|
|
||||
| [social.wxcafe.net](https://social.wxcafe.net) |Open registrations, federates everywhere, no moderation yet|Yes|Yes|
|
||||
| [social.wxcafe.net](https://social.wxcafe.net) |Open registrations, queer people, activists, safe as much as possible |Yes|Yes|
|
||||
| [octodon.social](https://octodon.social) |Open registrations, federates everywhere, cutest instance yet|Yes|Yes|
|
||||
| [mastodon.club](https://mastodon.club)|Open Registration, Open Federation, Mostly Canadians|Yes|No|
|
||||
| [mastodon.irish](https://mastodon.irish)|Open Registration|Yes|No|
|
||||
| [hostux.social](https://hostux.social) |N/A|Yes|Yes|
|
||||
| [social.alex73630.xyz](https://social.alex73630.xyz) |Francophones|Yes|Yes|
|
||||
| [oc.todon.fr](https://oc.todon.fr) |Modérée et principalement francophone, pas de tolérances pour misogynie/LGBTphobies/validisme/etc.|Yes|Yes|
|
||||
|
@ -46,5 +47,6 @@ There is also a list at [instances.mastodon.xyz](https://instances.mastodon.xyz)
|
|||
| [status.dissidence.ovh](https://status.dissidence.ovh)|N/A|Yes|Yes|
|
||||
| [mastodon.cc](https://mastodon.cc)|Art|Yes|No|
|
||||
| [mastodon.technology](https://mastodon.technology)|Open registrations, federates everywhere, for tech folks|Yes|No|
|
||||
| [mastodon.systemlab.fr](https://mastodon.systemlab.fr/)|Le mastodon Français, informatique, jeux-vidéos, gaming et hébergement.|Yes|No|
|
||||
|
||||
Let me know if you start running one so I can add it to the list! (Alternatively, add it yourself as a pull request).
|
||||
|
|
87
scalingo.json
Normal file
87
scalingo.json
Normal file
|
@ -0,0 +1,87 @@
|
|||
{
|
||||
"name": "Mastodon",
|
||||
"description": "A GNU Social-compatible microblogging server",
|
||||
"repository": "https://github.com/johnsudaar/mastodon",
|
||||
"logo": "https://github.com/tootsuite/mastodon/raw/master/app/assets/images/logo.png",
|
||||
"env": {
|
||||
"LOCAL_DOMAIN": {
|
||||
"description": "The domain that your Mastodon instance will run on (this can be appname.scalingo.io or a custom domain)",
|
||||
"required": true
|
||||
},
|
||||
"LOCAL_HTTPS": {
|
||||
"description": "Will your domain support HTTPS? (Automatic for *.scalingo.io, requires manual configuration for custom domains)",
|
||||
"value": "true",
|
||||
"required": true
|
||||
},
|
||||
"PAPERCLIP_SECRET": {
|
||||
"description": "The secret key for storing media files",
|
||||
"generator": "secret"
|
||||
},
|
||||
"SECRET_KEY_BASE": {
|
||||
"description": "The secret key base",
|
||||
"generator": "secret"
|
||||
},
|
||||
"SINGLE_USER_MODE": {
|
||||
"description": "Should the instance run in single user mode? (Disable registrations, redirect to front page)",
|
||||
"value": "false",
|
||||
"required": true
|
||||
},
|
||||
"S3_ENABLED": {
|
||||
"description": "Should Mastodon use Amazon S3 for storage? This is highly recommended, as Scalingo does not have persistent file storage (files will be lost).",
|
||||
"value": "true",
|
||||
"required": false
|
||||
},
|
||||
"S3_BUCKET": {
|
||||
"description": "Amazon S3 Bucket",
|
||||
"required": false
|
||||
},
|
||||
"S3_REGION": {
|
||||
"description": "Amazon S3 region that the bucket is located in",
|
||||
"required": false
|
||||
},
|
||||
"AWS_ACCESS_KEY_ID": {
|
||||
"description": "Amazon S3 Access Key",
|
||||
"required": false
|
||||
},
|
||||
"AWS_SECRET_ACCESS_KEY": {
|
||||
"description": "Amazon S3 Secret Key",
|
||||
"required": false
|
||||
},
|
||||
"SMTP_SERVER": {
|
||||
"description": "Hostname for SMTP server, if you want to enable email",
|
||||
"required": false
|
||||
},
|
||||
"SMTP_PORT": {
|
||||
"description": "Port for SMTP server",
|
||||
"required": false
|
||||
},
|
||||
"SMTP_LOGIN": {
|
||||
"description": "Username for SMTP server",
|
||||
"required": false
|
||||
},
|
||||
"SMTP_PASSWORD": {
|
||||
"description": "Password for SMTP server",
|
||||
"required": false
|
||||
},
|
||||
"SMTP_DOMAIN": {
|
||||
"description": "Domain for SMTP server. Will default to instance domain if blank.",
|
||||
"required": false
|
||||
},
|
||||
"SMTP_FROM_ADDRESS": {
|
||||
"description": "Address to send emails from",
|
||||
"required": false
|
||||
},
|
||||
"BUILDPACK_URL": {
|
||||
"description": "Internal scalingo configuration",
|
||||
"required": true,
|
||||
"value": "https://github.com/Scalingo/multi-buildpack.git"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"postdeploy": "bundle exec rails db:migrate && bundle exec rails db:seed"
|
||||
},
|
||||
"addons": [
|
||||
"scalingo-postgresql",
|
||||
"scalingo-redis"
|
||||
]
|
||||
}
|
Reference in a new issue