5
0
Fork 0
mirror of https://0xacab.org/sutty/sutty synced 2024-11-23 00:56:22 +00:00

Merge branch 'rails' into issue-14339

This commit is contained in:
f 2024-05-02 15:55:50 -03:00
commit 7a03269aa3
No known key found for this signature in database
63 changed files with 1434 additions and 51 deletions

View file

@ -6,9 +6,15 @@
- paths: - paths:
- "vendor/ruby" - "vendor/ruby"
- ".bundle" - ".bundle"
key:
files:
- "Gemfile.lock"
.cache-node: &cache-node .cache-node: &cache-node
- paths: - paths:
- "node_modules" - "node_modules"
key:
files:
- "yarn.lock"
.cache-task: &cache-task .cache-task: &cache-task
- paths: - paths:
- ".task" - ".task"
@ -90,7 +96,7 @@ rubocop:
- *apk-add - *apk-add
- *disable-hainish - *disable-hainish
script: script:
- "./bin/modified_files | ./bin/with_extension rb | xargs -r go-task bundle -- exec rubocop" - "go-task rubocop"
haml: haml:
stage: "test" stage: "test"
cache: cache:
@ -101,4 +107,4 @@ haml:
- *apk-add - *apk-add
- *disable-hainish - *disable-hainish
script: script:
- "./bin/modified_files | ./bin/with_extension haml | xargs -r go-task bundle -- exec haml-lint" - "go-task haml-lint"

View file

@ -183,3 +183,15 @@ tasks:
- "{{.HAINISH}} gem install bundler-audit" - "{{.HAINISH}} gem install bundler-audit"
status: status:
- "test -f ../hain/usr/bin/bundler-audit" - "test -f ../hain/usr/bin/bundler-audit"
rubocop:
desc: "Ruby linting"
deps:
- "gems"
cmds:
- "./bin/modified_files | ./bin/with_extension rb | xargs -r {{.HAINISH}} bundle exec rubocop {{.CLI_ARGS}}"
haml-lint:
desc: "HAML linting"
deps:
- "gems"
cmds:
- "./bin/modified_files | ./bin/with_extension haml | xargs -r {{.HAINISH}} bundle exec haml-lint {{.CLI_ARGS}}"

View file

@ -577,3 +577,27 @@ $bezier: cubic-bezier(0.75, 0, 0.25, 1);
} }
} }
} }
// details styles
.details {
summary {
list-style: none;
cursor: default;
position: relative;
}
summary::after {
content: '';
font-size: 1.8rem;
position: absolute;
left: 97%;
bottom: 3%;
transform: rotate(180deg);
}
&[open] {
& > summary {
&::after {
transform: rotate(90deg);
}
}
}
}

View file

@ -8,6 +8,10 @@ $cyan: #13fefe;
--color: #{$cyan}; --color: #{$cyan};
} }
.btn {
background-color: $white;
}
.btn-secondary { .btn-secondary {
background-color: $white; background-color: $white;
color: $black; color: $black;
@ -26,3 +30,5 @@ $cyan: #13fefe;
box-shadow: 0 0 0 0.2rem $cyan; box-shadow: 0 0 0 0.2rem $cyan;
} }
} }

View file

@ -11,6 +11,7 @@ class ApplicationController < ActionController::Base
before_action :configure_permitted_parameters, if: :devise_controller? before_action :configure_permitted_parameters, if: :devise_controller?
before_action :notify_unconfirmed_email, unless: :devise_controller? before_action :notify_unconfirmed_email, unless: :devise_controller?
around_action :set_locale around_action :set_locale
after_action :store_location!
rescue_from Pundit::NilPolicyError, with: :page_not_found rescue_from Pundit::NilPolicyError, with: :page_not_found
rescue_from ActionController::RoutingError, with: :page_not_found rescue_from ActionController::RoutingError, with: :page_not_found
@ -27,6 +28,16 @@ class ApplicationController < ActionController::Base
end end
private private
# Traer datos de muestra de la cola de moderación
def dummy_data
@moderation_queue = YAML.safe_load(File.read(Rails.root.join('db', 'seeds', 'moderation_queue.yaml')))
@remote_profile = YAML.safe_load(File.read(Rails.root.join('db', 'seeds', 'remote_profile.yaml')))
@instances = YAML.safe_load(File.read(Rails.root.join('db', 'seeds', 'instances.yaml')))
@blocklists= YAML.safe_load(File.read(Rails.root.join('db', 'seeds', 'blocklists.yml')))
@moderation_queue.each do |activity|
activity['attributedTo'] = @remote_profile
end
end
def notify_unconfirmed_email def notify_unconfirmed_email
return unless current_usuarie return unless current_usuarie
@ -115,6 +126,17 @@ class ApplicationController < ActionController::Base
def after_sign_in_path_for(resource) def after_sign_in_path_for(resource)
session[:locale] = nil session[:locale] = nil
sites_path super
end end
# Guardar la ubicación para que devise redirija a donde íbamos, a
# menos que estemos recibiendo información o intentando ingresar.
def store_location!
return if request.xhr?
return unless request.request_method_symbol == :GET
return if devise_controller? && !is_a?(Devise::RegistrationsController) && params[:action] != 'edit'
session[:usuarie_return_to] = request.fullpath
end
end end

View file

@ -0,0 +1,20 @@
# frozen_string_literal: true
# Cola de moderación de ActivityPub
class ModerationQueueController < ApplicationController
# Cola de moderación viendo todo el sitio
def index
dummy_data
end
# Perfil remoto de usuarie
def remote_profile
dummy_data
end
# todon.nl está usando /api/v2/instance
# mauve.moe usa /api/v1/instance
def instances
dummy_data
end
end

View file

@ -38,6 +38,7 @@ class PostsController < ApplicationController
@usuarie = site.usuarie? current_usuarie @usuarie = site.usuarie? current_usuarie
@site_stat = SiteStat.new(site) @site_stat = SiteStat.new(site)
dummy_data
end end
def show def show
@ -81,6 +82,7 @@ class PostsController < ApplicationController
authorize post authorize post
breadcrumb post.title.value, site_post_path(site, post, locale: locale), match: :exact breadcrumb post.title.value, site_post_path(site, post, locale: locale), match: :exact
breadcrumb 'posts.edit', '' breadcrumb 'posts.edit', ''
dummy_data
end end
def update def update

View file

@ -15,6 +15,19 @@ class SitesController < ApplicationController
fresh_when @sites fresh_when @sites
end end
# Genera la caja del estado para HTMX
def status
authorize site
render('sites/status', layout: false) if stale? site
end
def button
authorize site
render('sites/build', layout: false)
end
# No tenemos propiedades de un sitio aún, así que vamos al listado de # No tenemos propiedades de un sitio aún, así que vamos al listado de
# artículos # artículos
def show def show

View file

@ -0,0 +1,106 @@
import { Controller } from "stimulus";
// https://getbootstrap.com/docs/4.6/components/dropdowns/#single-button
export default class extends Controller {
static targets = ["dropdown", "button", "item"];
// Al iniciar el controlador
connect() {
// Llevar la cuenta del item con foco
this.data.set("item", -1);
// Gestionar las teclas
this.keydownEvent = this.keydown.bind(this);
this.element.addEventListener("keydown", this.keydownEvent);
// Gestionar el foco
this.focusinEvent = this.focusin.bind(this);
}
// Al eliminar el controlador (al pasar a otra página)
disconnect() {
// Eliminar la gestión de teclas
this.element.removeEventListener("keydown", this.keydownEvent);
// Eliminar la gestión del foco
document.removeEventListener("focusin", this.focusinEvent);
}
// Mostrar u ocultar
toggle(event) {
(this.buttonTarget.ariaExpanded === "false") ? this.show() : this.hide();
}
// Mostrar
show() {
this.buttonTarget.ariaExpanded = "true";
this.element.classList.add("show");
this.dropdownTarget.classList.add("show");
// Activar la gestión del foco
document.addEventListener("focusin", this.focusinEvent);
}
// Ocultar
hide() {
this.buttonTarget.ariaExpanded = "false";
this.element.classList.remove("show");
this.dropdownTarget.classList.remove("show");
// Volver al inicio el foco de items
this.data.set("item", -1);
// Desactivar la gestión del foco
document.removeEventListener("focusin", this.focusinEvent);
}
// Gestionar el foco
focusin(event) {
const item = this.itemTargets.find(x => x === event.target);
// Si el foco se coloca sobre elementos del controlador, no hacer
// nada
if (event.target === this.buttonTarget || item) {
// Si es un item, el comportamiento de las flechas verticales y el
// Tab tiene que ser igual
if (item) this.data.set("item", this.itemTargets.indexOf(item));
return;
}
// De lo contrario, ocultar
this.hide();
}
// Gestionar las teclas
keydown(event) {
const initial = parseInt(this.data.get("item"));
let item = initial;
switch (event.keyCode) {
case 27:
// Esc cierra el menú y devuelve el foco
this.hide();
this.buttonTarget.focus();
break;
case 38:
// Moverse hacia arriba con tope en el primer item
if (item > -1) item--;
break;
case 40:
// Moverse hacia abajo con tope en el último ítem, si el
// dropdown estaba cerrado, abrirlo.
if (item === -1) this.show();
if (item <= this.itemTargets.length) item++;
break;
}
// Si cambió la posición del ítem, darle foco y actualizar el
// contador.
if (initial !== item) {
this.itemTargets[item]?.focus();
this.data.set("item", item);
}
}
}

View file

@ -0,0 +1,7 @@
// Cancela las peticiones pendientes de htmx para todos los elementos al
// cambiar de página.
document.addEventListener("turbolinks:click", () => {
for (const hx of document.querySelectorAll("[hx-get]")) {
window.htmx.trigger(hx, "htmx:abort");
}
});

View file

@ -7,3 +7,4 @@ import './timezone'
import './turbolinks-anchors' import './turbolinks-anchors'
import './validation' import './validation'
import './new_editor' import './new_editor'
import './htmx_abort'

View file

@ -9,9 +9,16 @@ try {
host: window.env.PANEL_URL host: window.env.PANEL_URL
}); });
const ignoredErrors = ["htmx:afterRequest", "htmx:sendAbort"];
console.originalError = console.error; console.originalError = console.error;
console.error = (...e) => { console.error = (...e) => {
const msg = e.join(" ");
if (!ignoredErrors.some(x => msg.includes(x))) {
window.airbrake.notify(e.join(" ")); window.airbrake.notify(e.join(" "));
}
return console.originalError(...e); return console.originalError(...e);
}; };
} catch(e) { } catch(e) {
@ -33,3 +40,5 @@ import 'chartkick/chart.js'
Rails.start() Rails.start()
Turbolinks.start() Turbolinks.start()
ActiveStorage.start() ActiveStorage.start()
window.htmx = require('htmx.org/dist/htmx.js')

View file

@ -14,6 +14,8 @@ module Jekyll
extend ActiveSupport::Concern extend ActiveSupport::Concern
included do included do
DATA_EXTENSIONS = %w[.yaml .yml .json .csv .tsv].freeze
def read_data_to(dir, data) def read_data_to(dir, data)
return unless File.directory?(dir) && !@entry_filter.symlink?(dir) return unless File.directory?(dir) && !@entry_filter.symlink?(dir)
@ -24,7 +26,7 @@ module Jekyll
if File.directory?(path) if File.directory?(path)
read_data_to(path, data[sanitize_filename(entry)] = {}) read_data_to(path, data[sanitize_filename(entry)] = {})
else elsif DATA_EXTENSIONS.include?(File.extname(entry))
key = sanitize_filename(File.basename(entry, ".*")) key = sanitize_filename(File.basename(entry, ".*"))
data[key] = read_data_file(path) data[key] = read_data_file(path)
end end

View file

@ -87,7 +87,7 @@ class DeployDistributedPress < Deploy
# @return [Array] # @return [Array]
def gateway_urls def gateway_urls
remote_info.dig(:distributed_press, :links)&.values&.map do |protocol| remote_info.dig(:distributed_press, :links)&.values&.map do |protocol|
[ protocol[:link], protocol[:gateway] ] [protocol[:link]]
end&.flatten&.compact&.select do |link| end&.flatten&.compact&.select do |link|
link.include? '://' link.include? '://'
end || [] end || []

View file

@ -389,9 +389,11 @@ class Site < ApplicationRecord
end end
def reload def reload
super super.tap do |s|
reload_jekyll! reload_jekyll!
end end
self
end
def configuration def configuration
return @configuration if @configuration return @configuration if @configuration

View file

@ -14,6 +14,10 @@ class SitePolicy
true true
end end
def status?
true
end
# Puede ver la versión privada del sitio? # Puede ver la versión privada del sitio?
def private? def private?
edit? && site.deploys.find_by_type('DeployPrivate') edit? && site.deploys.find_by_type('DeployPrivate')
@ -57,6 +61,10 @@ class SitePolicy
show? && usuarie? show? && usuarie?
end end
def button?
show?
end
def enqueue? def enqueue?
build? build?
end end

View file

@ -0,0 +1,9 @@
-# Componente Listas de bloqueo de Instancias
.card.mt-3.mb-3
.card-body
.d-flex.flex-row
= render 'components/checkbox', id: blocklist['id'] do
%span.h4= blocklist["title"]
%p.mb-0
%a{ href: blocklist['link'] }= blocklist['title']

View file

@ -0,0 +1,2 @@
- @blocklists.each do |blocklist|
= render 'components/block_list', blocklist: blocklist

View file

@ -0,0 +1,3 @@
-# Componente Botón general Moderación
%button.btn{ href: href, class: local_assigns[:class] }= text

View file

@ -0,0 +1,4 @@
-# Componente Checkbox
.custom-control.custom-checkbox
%input.custom-control-input{ type: 'checkbox', id: id, name: id, class: local_assigns[:class] }
%label.custom-control-label{ for: id }= yield

View file

@ -0,0 +1,8 @@
-# Componente Botonera de Comentarios
- btn_class = 'btn-secondary py-1 px-2'
= render 'components/btn_base', text: t('.text_pause'), class: btn_class, href: ''
= render 'components/btn_base', text: t('.text_reject'), class: btn_class, href: ''
= render 'components/btn_base', text: t('.text_accept'), class: btn_class, href: ''
= render 'components/btn_base', text: t('.text_reply'), class: btn_class, href: ''
= render 'components/btn_base', text: t('.text_report'), class: btn_class, href: ''

View file

@ -0,0 +1,3 @@
= render 'components/dropdown_item', text: t('.submenu_pause'), path: '/'
= render 'components/dropdown_item', text: t('.submenu_accept'), path: '/'
= render 'components/dropdown_item', text: t('.submenu_reject'), path: '/'

View file

@ -0,0 +1,6 @@
.d-flex.py-2
= render 'components/dropdown', text: t('.text_checked') do
= render 'components/comments_checked_submenu'
= render 'components/dropdown', text: t('.text_show') do
= render 'components/comments_show_submenu'

View file

@ -0,0 +1,4 @@
= render 'components/dropdown_item', text: t('.submenu_pause'), path: '/'
= render 'components/dropdown_item', text: t('.submenu_accept'), path: '/'
= render 'components/dropdown_item', text: t('.submenu_report'), path: '/'
= render 'components/dropdown_item', text: t('.submenu_reject'), path: '/'

View file

@ -0,0 +1,34 @@
-#
@param :text [String] Contenido del botón
@param :button_classes [Array] Clases para el botón
@param :dropdown_classes [Array] Clases para el listado
@yield Un bloque que renderiza components/dropdown_item
- button_classes = local_assigns[:button_classes]&.join(' ')
- dropdown_classes = local_assigns[:dropdown_classes]&.join(' ')
.btn-group{
data: {
controller: 'dropdown'
}
}
%button.btn.dropdown-toggle{
type: 'button',
class: button_classes,
data: {
toggle: 'true',
display: 'static',
action: 'dropdown#toggle',
target: 'dropdown.button'
},
aria: {
expanded: 'false'
}
}
= text
.dropdown-menu{
class: dropdown_classes,
data: {
target: 'dropdown.dropdown'
}
}
= yield

View file

@ -0,0 +1,4 @@
-#
@param :text [String] Contenido del link
@param :path [String] Link
= link_to text, path, class: 'dropdown-item', data: { target: 'dropdown.item' }

View file

@ -0,0 +1,6 @@
-# Componente botonera de moderación de Instancias
- btn_class = 'btn btn-secondary'
= render 'components/btn_base', text: t('.text_check'), class: btn_class, href: ''
= render 'components/btn_base', text: t('.text_allow'), class: btn_class, href: ''
= render 'components/btn_base', text: t('.text_deny'), class: btn_class, href: ''

View file

@ -0,0 +1,3 @@
= render 'components/dropdown_item', text: t('.submenu_case'), path: '/'
= render 'components/dropdown_item', text: t('.submenu_allow'), path: '/'
= render 'components/dropdown_item', text: t('.submenu_reject'), path: '/'

View file

@ -0,0 +1,6 @@
.d-flex.py-2
= render 'components/dropdown', text: t('.text_checked') do
= render 'components/instances_checked_submenu'
= render 'components/dropdown', text: t('.text_show') do
= render 'components/comments_show_submenu'

View file

@ -0,0 +1,2 @@
= render 'components/dropdown_item', text: t('.submenu_allow'), path: '/'
= render 'components/dropdown_item', text: t('.submenu_reject'), path: '/'

View file

@ -0,0 +1,7 @@
-# Componente Botonera de Moderación de Cuentas (Remote_profile)
- btn_class = 'btn-secondary'
= render 'components/btn_base', text: t('.text_approve'), class: btn_class, href: ''
= render 'components/btn_base', text: t('.text_check'), class: btn_class, href: ''
= render 'components/btn_base', text: t('.text_deny'), class: btn_class, href: ''
= render 'components/btn_base', text: t('.text_report'), class: btn_class, href: ''

View file

@ -0,0 +1,4 @@
= render 'components/dropdown_item', text: t('.submenu_pause'), path: '/'
= render 'components/dropdown_item', text: t('.submenu_accept'), path: '/'
= render 'components/dropdown_item', text: t('.submenu_reject'), path: '/'
= render 'components/dropdown_item', text: t('.submenu_block'), path: '/'

View file

@ -0,0 +1,6 @@
.d-flex.py-2
= render 'components/dropdown', text: t('.text_checked') do
= render 'components/profiles_checked_submenu'
= render 'components/dropdown', text: t('.text_show') do
= render 'components/profiles_show_submenu'

View file

@ -0,0 +1,3 @@
= render 'components/dropdown_item', text: t('.submenu_accept'), path: '/'
= render 'components/dropdown_item', text: t('.submenu_reject'), path: '/'
= render 'components/dropdown_item', text: t('.submenu_block'), path: '/'

View file

@ -0,0 +1,6 @@
-# Detail Cola de Moderación
%details.details.py-2
%summary
%h3.py-2.pr-2= summary
= yield

View file

@ -0,0 +1,11 @@
.row.no-gutters.pt-2
.col-1
= render 'components/checkbox', id: profile['id']
.col-11
%h4
%a{href: profile['id']}= profile['preferredUsername']
=profile['summary'].html_safe
-# Botones de Moderación
.d-flex.pb-4
= render 'components/profiles_btn_box'

View file

@ -0,0 +1,12 @@
.row.no-gutters.pt-2
.col-1.d-flex.align-items-center
= render 'components/checkbox', id: moderation_queue.first['id']
.col-11
-# Filtros
= render 'components/profiles_filters'
- @moderation_queue.map{ |c| c['attributedTo'] }.uniq.each do |remote_profile|
%hr
= render 'account', profile: remote_profile

View file

@ -0,0 +1,5 @@
.form-group
= label_tag "custom_blocklist", t('moderation_queue.instances.custom_block')
= text_area_tag "custom_blocklist", nil, class: 'form-control'
%button.btn.btn-secondary.mt-3{ type: 'submit' }= t('moderation_queue.instances.submit')

View file

@ -0,0 +1,27 @@
-# Componente Comentario
.row.no-gutters
.col-1
= render 'components/checkbox', id: comment['id']
.col-11
.row.no-gutters
.col.col-lg-10.d-inline-flex.justify-content-between
%h4
%a{ href: comment['attributedTo'] }= profile['preferredUsername']
= render 'layouts/time', time: comment['published']
- if comment['inReplyTo']
.row.no-gutters
.col.p-0
%p
%span= t('.reply_to')
%span
%a{ href: comment['inReplyTo'] }= comment['inReplyTo']
.row.no-gutters
.col.p-0
- if comment['summary']
- summary = comment['summary']
= render 'layouts/details', summary: summary do
%p= comment['content'].html_safe
- else
%p= comment['content'].html_safe

View file

@ -0,0 +1,14 @@
.row.no-gutters.pt-2
.col-1.d-flex.align-items-center
= render 'components/checkbox', id: moderation_queue.first['id']
.col-md-9
-# Filtros
= render 'components/comments_filters'
- moderation_queue.each do |comment|
%hr
= render 'comment', comment: comment, profile: comment['attributedTo']
-# Botones moderación
.d-flex.justify-content-center
= render 'components/comments_btn_box', comment: comment

View file

@ -0,0 +1,20 @@
- host = instance['domain']
- host ||= instance['uri']
- hosthttps = "https://#{host}"
.row.no-gutters.pt-2
.col-1
= render 'components/checkbox', id: host
.col-11
%h4
%a{ href: hosthttps }= instance['title']
%p= instance['description'].html_safe
%dl.d-inline-flex
%dt.pr-2= t('.users')
%dd
= instance.dig('usage', 'users', 'active_month')
= instance.dig('stats', 'user_count')
-# Botones moderación
.d-flex.pb-4
= render 'components/instances_btn_box'

View file

@ -0,0 +1,16 @@
.row.no-gutters.pt-2
.col-1.d-flex.align-items-center
= render 'components/checkbox', id: moderation_queue.first['id']
.col-11
-# Filtros
= render 'components/instances_filters'
- @instances.each do |instance|
%hr
= render 'moderation_queue/instance', instance: instance
%hr
%h3.mt-5= t('moderation_queue.instances.title')
%lead= t('moderation_queue.instances.description')
= render 'components/block_lists', blocklists: @blocklists
= render 'moderation_queue/block_instances_textarea'

View file

@ -0,0 +1,28 @@
-# Componente Remote_Profile
.flex.py-2.mx-2
%dl
%dt= t('.profile_name')
%dd= remote_profile['name']
%dt= t('.preferred_name')
%dd= remote_profile['preferredUsername']
%dt= t('.profile_id')
%dd
%a{ href: 'https://mastodon.mauve.moe/users/mauve' }= remote_profile['id']
%dt= t('.profile_published')
%dd
= render 'layouts/time', time: remote_profile['published']
%dt= t('.profile_summary')
%dd= remote_profile['summary'].html_safe
= render 'moderation_queue/comments', moderation_queue: @moderation_queue
%dl.mt-5
%dt= t('.profile_name')
%dd= remote_profile['name']
-# Botones de Moderación
= render 'components/profiles_btn_box'

View file

@ -0,0 +1,16 @@
.row.justify-content-center
.col-md-8
%h1= t('.title')
.row
.col
- summary = t('.instances')
= render 'layouts/details', summary: summary do
= render 'moderation_queue/instances', site: @site, post: @post, moderation_queue: @moderation_queue
%hr
- summary = t('.accounts')
= render 'layouts/details', summary: summary do
= render 'moderation_queue/accounts', site: @site, post: @post, moderation_queue: @moderation_queue
%hr
- summary = t('.comments')
= render 'layouts/details', summary: summary do
= render 'moderation_queue/comments', site: @site, post: @post, moderation_queue: @moderation_queue

View file

@ -0,0 +1,4 @@
.row.justify-content-center
.col-md-8
%h1= t('.profile')
= render 'moderation_queue/remote_profile', remote_profile: @remote_profile

View file

@ -0,0 +1,14 @@
.row.no-gutters.pt-2
.col-1
= render 'components/checkbox', id: moderation_queue.first['id']
.col-11
-# Filtros
= render 'components/comments_filters'
- moderation_queue.each do |comment|
%hr
= render 'moderation_queue/comment', comment: comment, profile: comment['attributedTo']
-# Botones moderación
.d-flex
= render 'components/comments_btn_box'

View file

@ -1,6 +1,8 @@
.row.justify-content-center .row.justify-content-center
.col-md-8 .col-md-8
= render 'layouts/details', summary: "Post" do - summary = t('posts.edit.post')
= render 'layouts/details', summary: summary do
= render 'posts/form', site: @site, post: @post = render 'posts/form', site: @site, post: @post
= render 'layouts/details', summary: t('.moderation_queue') do - summary = t('posts.edit.moderation_queue')
= render 'layouts/details', summary: summary do
= render 'posts/moderation_queue', site: @site, post: @post, moderation_queue: @moderation_queue = render 'posts/moderation_queue', site: @site, post: @post, moderation_queue: @moderation_queue

View file

@ -3,7 +3,6 @@
= render 'sites/header', site: @site = render 'sites/header', site: @site
= render 'sites/status', site: @site = render 'sites/status', site: @site
= render 'sites/build', site: @site, class: 'btn-block' = render 'sites/build', site: @site, class: 'btn-block'
%h3= t('posts.new') %h3= t('posts.new')
@ -126,7 +125,7 @@
= post.order = post.order
%td.text-nowrap %td.text-nowrap
- if @usuarie || policy(post).edit? - if @usuarie || policy(post).edit?
= link_to t('posts.edit'), edit_site_post_path(@site, post.path), class: 'btn btn-secondary btn-block' = link_to t('posts.edit_post'), edit_site_post_path(@site, post.path), class: 'btn btn-secondary btn-block'
- if @usuarie || policy(post).destroy? - if @usuarie || policy(post).destroy?
= link_to t('posts.destroy'), site_post_path(@site, post.path), class: 'btn btn-secondary btn-block', method: :delete, data: { confirm: t('posts.confirm_destroy') } = link_to t('posts.destroy'), site_post_path(@site, post.path), class: 'btn btn-secondary btn-block', method: :delete, data: { confirm: t('posts.confirm_destroy') }

View file

@ -2,7 +2,7 @@
.row.justify-content-center .row.justify-content-center
.col-md-8 .col-md-8
%article.content.table-responsive-md %article.content.table-responsive-md
= link_to t('posts.edit'), = link_to t('posts.edit_post'),
edit_site_post_path(@site, @post.id), edit_site_post_path(@site, @post.id),
class: 'btn btn-secondary btn-block' class: 'btn btn-secondary btn-block'

View file

@ -1,4 +1,5 @@
- if policy(site).build? - if policy(site).build?
%div{ 'hx-get': site_button_path(site, class: local_assigns[:class]), 'hx-trigger': 'every 10s', 'hx-swap': 'outerHTML' }
= form_tag site_enqueue_path(site), = form_tag site_enqueue_path(site),
method: :post, method: :post,
class: 'form-inline inline' do class: 'form-inline inline' do
@ -6,4 +7,4 @@
class: "btn btn-secondary #{local_assigns[:class]}", class: "btn btn-secondary #{local_assigns[:class]}",
title: site.enqueued? ? t('help.sites.enqueued') : t('help.sites.enqueue'), title: site.enqueued? ? t('help.sites.enqueued') : t('help.sites.enqueue'),
data: { disable_with: t('sites.enqueued') }, data: { disable_with: t('sites.enqueued') },
disabled: site.enqueued? disabled: !site.waiting?

View file

@ -1,3 +1,4 @@
- cache site do
- link = nil - link = nil
- if site.not_published_yet? - if site.not_published_yet?
- message = t('.not_published_yet') - message = t('.not_published_yet')
@ -17,5 +18,7 @@
- message = t('.available') - message = t('.available')
- link = true - link = true
-# TODO: Calcular cada cuánto sería óptimo recargar
%div{ 'hx-get': site_status_path(site), 'hx-trigger': 'every 10s', 'hx-swap': 'outerHTML' }
= render 'bootstrap/alert' do = render 'bootstrap/alert' do
= link_to_if link, message.html_safe, site_build_stats_path(site), class: 'alert-link' = link_to_if link, message.html_safe, site_build_stats_path(site), class: 'alert-link'

View file

@ -0,0 +1 @@
= render 'sites/build', site: @site, class: params.permit(:class)[:class]

View file

@ -0,0 +1 @@
= render 'sites/status', site: @site

View file

@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
set -e set -e
test -n "${CI_MERGE_REQUEST_DIFF_BASE_SHA}" CI_MERGE_REQUEST_DIFF_BASE_SHA="${CI_MERGE_REQUEST_DIFF_BASE_SHA:-origin/rails}"
git diff --name-status ${CI_MERGE_REQUEST_DIFF_BASE_SHA} \ git diff --name-status ${CI_MERGE_REQUEST_DIFF_BASE_SHA} \
| grep -v "^D" \ | grep -v "^D" \

View file

@ -1,4 +1,130 @@
en: en:
date:
format: '%m/%d/%Y'
published_at: "Published at"
last_modified_at: "Last modification"
abbr_day_names:
- Mon
- Tue
- Wed
- Thu
- Fri
- Sat
- Sun
day_names:
- Monday
- Tuesday
- Wednesday
- Thursday
- Friday
- Saturday
- Sunday
abbr_month_names:
- Jan
- Feb
- Mar
- Apr
- May
- Jun
- Jul
- Aug
- Sep
- Oct
- Nov
- Dec
month_names:
- January
- February
- March
- April
- May
- June
- July
- August
- September
- October
- November
- December
time:
am: am
pm: pm
format: '%-I:%M %p'
components:
instances_filters:
text_show: Show
text_checked: With selected
instances_checked_submenu:
submenu_case: Check case by case
submenu_allow: Allow everything
submenu_reject: Reject
instances_show_submenu:
submenu_allow: Allow
submenu_reject: Reject
comments_filters:
text_show: Show
text_checked: With selected
comments_checked_submenu:
submenu_pause: Pause
submenu_accept: Accept
submenu_reject: Reject
comments_show_submenu:
submenu_pause: Pause
submenu_accept: Accept
submenu_report: Report
submenu_reject: Reject
profiles_filters:
text_show: Show
text_checked: With selected
profiles_checked_submenu:
submenu_pause: Pause
submenu_accept: Accept
submenu_reject: Reject
submenu_block: Block
profiles_show_submenu:
submenu_accept: Accept
submenu_block: Block
submenu_reject: Reject
block_lists:
title: Block lists
comments_btn_box:
text_pause: Pause
text_reject: Reject
text_accept: Accept
text_reply: Reply
text_report: Report
instances_btn_box:
text_check: Check case by case
text_allow: Allow everything
text_deny: Block instance
profiles_btn_box:
text_approve: Always approve
text_check: Always check
text_deny: Block
text_report: Report
moderation_queue:
index:
title: Moderation
instances: Instances
accounts: Accounts
comments: Comments
comment:
source_profile: Source Profile
reply_to: Reply to
remote_profile:
user: Username
profile: Profile
profile_name: Profile name
preferred_name: Name in Fediverse
profile_id: ID
profile_published: Published
profile_summary: Summary
instances:
title: My block lists
description: Description
custom_block: Custom block lists
submit: Save block lists
instance:
users: "Users:"
dark: Dark dark: Dark
dir: ltr dir: ltr
en: English en: English
@ -389,7 +515,7 @@ en:
static_file_migration: 'File migration' static_file_migration: 'File migration'
find_and_replace: 'Search and replace' find_and_replace: 'Search and replace'
status: status:
building: "Your site is building, refresh this page in <time datetime=\"PT%{seconds}S\">%{average_time}</time>." building: "Your site is building, it will be ready in <time datetime=\"PT%{seconds}S\">%{average_time}</time>."
not_published_yet: "Your site is being published for the first time, please wait up to 1 minute..." not_published_yet: "Your site is being published for the first time, please wait up to 1 minute..."
available: "Your site is available! Click here to find all the different ways to visit it." available: "Your site is available! Click here to find all the different ways to visit it."
awaiting_publication: "There are unpublished changes. Click the button below and wait a moment to find them on your site." awaiting_publication: "There are unpublished changes. Click the button below and wait a moment to find them on your site."
@ -578,7 +704,10 @@ en:
categories: 'Everything' categories: 'Everything'
index: index:
search: 'Search' search: 'Search'
edit: 'Edit' edit_post: 'Edit'
edit:
moderation_queue: Moderation Queue
post: Post
preview: preview:
btn: 'Preliminary version' btn: 'Preliminary version'
alert: 'Not every article type has a preliminary version' alert: 'Not every article type has a preliminary version'

View file

@ -1,4 +1,130 @@
es: es:
date:
format: '%d/%m/%Y'
published_at: "Publicado en"
last_modified_at: "Última modificación"
abbr_day_names:
- Lun
- Mar
- Mié
- Jue
- Vie
- Sáb
- Dom
day_names:
- Lunes
- Martes
- Miércoles
- Jueves
- Viernes
- Sábado
- Domingo
abbr_month_names:
- Ene
- Feb
- Mar
- Abr
- May
- Jun
- Jul
- Ago
- Sep
- Oct
- Nov
- Dic
month_names:
- Enero
- Febrero
- Marzo
- Abril
- Mayo
- Junio
- Julio
- Agosto
- Septiembre
- Octubre
- Noviembre
- Diciembre
time:
am: am
pm: pm
format: '%-H:%M'
components:
instances_filters:
text_show: Ver
text_checked: Con los marcados
instances_checked_submenu:
submenu_case: Moderar caso por caso
submenu_allow: Permitir todo
submenu_reject: Rechazado
instances_show_submenu:
submenu_allow: Permitido
submenu_reject: Rechazado
comments_filters:
text_show: Ver
text_checked: Con los marcados
comments_checked_submenu:
submenu_pause: Pausado
submenu_accept: Aceptado
submenu_reject: Rechazado
comments_show_submenu:
submenu_pause: Pausado
submenu_accept: Aceptado
submenu_report: Reportado
submenu_reject: Rechazado
profiles_filters:
text_show: Ver
text_checked: Con los marcados
profiles_checked_submenu:
submenu_pause: Pausado
submenu_accept: Aceptado
submenu_reject: Rechazado
submenu_block: Bloqueado
profiles_show_submenu:
submenu_accept: Aceptado
submenu_block: Bloqueado
submenu_reject: Rechazado
block_lists:
title: Listas de bloqueo
comments_btn_box:
text_pause: Pausa
text_reject: Rechazar
text_accept: Aceptar Publicación
text_reply: Responder
text_report: Reportar
instances_btn_box:
text_check: Moderar caso por caso
text_allow: Permitir todo
text_deny: Bloquear instancia
profiles_btn_box:
text_approve: Aprobar siempre
text_check: Revisar siempre
text_deny: Bloquear
text_report: Reportar
moderation_queue:
index:
title: Actividades de moderación
instances: Instancias
accounts: Cuentas
comments: Comentarios
comment:
source_profile: Cuenta de Origen
reply_to: En respuesta a
remote_profile:
user: Nombre de usuario
profile: Cuenta de Origen
profile_name: Nombre de la Cuenta
preferred_name: Nombre en el Fediverso
profile_id: ID
profile_published: Publicada
profile_summary: Presentación
instances:
title: Mis listas de bloqueo
description: Descripción de listas de bloqueo
custom_block: Lista personalizada de bloqueo
submit: Guardar listas de bloqueo
instance:
users: "Usuaries:"
dark: Oscuro dark: Oscuro
es: Castellano es: Castellano
en: English en: English
@ -394,7 +520,7 @@ es:
static_file_migration: 'Migración de archivos' static_file_migration: 'Migración de archivos'
find_and_replace: 'Búsqueda y reemplazo' find_and_replace: 'Búsqueda y reemplazo'
status: status:
building: "Tu sitio se está publicando, recargá esta página en <time datetime=\"PT%{seconds}S\">%{average_time}</time>." building: "Tu sitio se está publicando, estará listo en <time datetime=\"PT%{seconds}S\">%{average_time}</time>."
not_published_yet: "Tu sitio se está publicando por primera vez, por favor espera hasta un minuto..." not_published_yet: "Tu sitio se está publicando por primera vez, por favor espera hasta un minuto..."
available: "¡Tu sitio está disponible! Cliqueá aquí para encontrar todas las formas en que podés visitarlo." available: "¡Tu sitio está disponible! Cliqueá aquí para encontrar todas las formas en que podés visitarlo."
awaiting_publication: "Hay cambios sin publicar, cliqueá el botón debajo y espera un momento para encontrarlos en tu sitio." awaiting_publication: "Hay cambios sin publicar, cliqueá el botón debajo y espera un momento para encontrarlos en tu sitio."
@ -520,6 +646,9 @@ es:
en: 'inglés' en: 'inglés'
ar: 'árabe' ar: 'árabe'
posts: posts:
edit:
moderation_queue: Comentarios
post: Contenido
prev: Página anterior prev: Página anterior
next: Página siguiente next: Página siguiente
empty: No hay artículos con estos parámetros de búsqueda. empty: No hay artículos con estos parámetros de búsqueda.
@ -586,7 +715,7 @@ es:
remove_filter_help: 'Quitar este filtro: %{filter}' remove_filter_help: 'Quitar este filtro: %{filter}'
index: index:
search: 'Buscar' search: 'Buscar'
edit: 'Editar' edit_post: 'Editar'
preview: preview:
btn: 'Versión preliminar' btn: 'Versión preliminar'
alert: 'No todos los tipos de artículos poseen vista preliminar :)' alert: 'No todos los tipos de artículos poseen vista preliminar :)'

View file

@ -37,6 +37,9 @@ Rails.application.routes.draw do
get 'pull', to: 'sites#fetch' get 'pull', to: 'sites#fetch'
post 'pull', to: 'sites#merge' post 'pull', to: 'sites#merge'
get 'status', to: 'sites#status'
get 'button', to: 'sites#button'
# Gestionar usuaries # Gestionar usuaries
get 'usuaries/invite', to: 'usuaries#invite' get 'usuaries/invite', to: 'usuaries#invite'
post 'usuaries/invite', to: 'usuaries#send_invitations' post 'usuaries/invite', to: 'usuaries#send_invitations'
@ -50,6 +53,10 @@ Rails.application.routes.draw do
get 'collaborate', to: 'collaborations#collaborate' get 'collaborate', to: 'collaborations#collaborate'
post 'collaborate', to: 'collaborations#accept_collaboration' post 'collaborate', to: 'collaborations#accept_collaboration'
get 'moderation_queue', to: 'moderation_queue#index'
get 'remote_profile', to: 'moderation_queue#remote_profile'
get 'instances', to: 'moderation_queue#instances'
# Gestionar artículos según idioma # Gestionar artículos según idioma
nested do nested do
scope '/(:locale)', constraint: /[a-z]{2}(-[A-Z]{2})?/ do scope '/(:locale)', constraint: /[a-z]{2}(-[A-Z]{2})?/ do

7
db/seeds/blocklists.yml Normal file
View file

@ -0,0 +1,7 @@
---
- id: gardenfence
title: Gardenfence
link: 'https://gardenfence.github.io/'
- id: lista
title: Lista
link: '#'

285
db/seeds/instances.yaml Normal file
View file

@ -0,0 +1,285 @@
---
- domain: todon.nl
title: Todon.nl
version: 4.2.3
source_url: https://github.com/mastodon/mastodon
description: Radicaal linkse anti-autoritaire server. Voor anarchisten, socialisten,
(klimaat)activisten, LHBTQIA+, antiracisten, antifascisten, antikapitalisten,
intersectionelen, veganisten, mensenrechten, enz.
usage:
users:
active_month: 372
thumbnail:
url: https://todon.nl/system/site_uploads/files/000/000/004/@1x/297e509bc8a81f62.png
blurhash: UXAw3zN4M|xsoga#WBay9DxntQRmITocofWE
versions:
"@1x": https://todon.nl/system/site_uploads/files/000/000/004/@1x/297e509bc8a81f62.png
"@2x": https://todon.nl/system/site_uploads/files/000/000/004/@2x/297e509bc8a81f62.png
languages:
- en
configuration:
urls:
streaming: wss://todon.nl
status: https://status.todon.eu
accounts:
max_featured_tags: 10
statuses:
max_characters: 1312
max_media_attachments: 4
characters_reserved_per_url: 23
media_attachments:
supported_mime_types:
- image/jpeg
- image/png
- image/gif
- image/heic
- image/heif
- image/webp
- image/avif
- video/webm
- video/mp4
- video/quicktime
- video/ogg
- audio/wave
- audio/wav
- audio/x-wav
- audio/x-pn-wave
- audio/vnd.wave
- audio/ogg
- audio/vorbis
- audio/mpeg
- audio/mp3
- audio/webm
- audio/flac
- audio/aac
- audio/m4a
- audio/x-m4a
- audio/mp4
- audio/3gpp
- video/x-ms-asf
image_size_limit: 16777216
image_matrix_limit: 33177600
video_size_limit: 103809024
video_frame_rate_limit: 120
video_matrix_limit: 8294400
polls:
max_options: 4
max_characters_per_option: 50
min_expiration: 300
max_expiration: 2629746
translation:
enabled: true
registrations:
enabled: false
approval_required: false
message: |
<p style="text-align: center"><strong>¡No pasarán!</strong></p>
<p>Je kunt tijdelijk geen nieuw account op Todon.nl aanvragen.</p>
<!--<p>Je kunt tussen 9u00 en 23u00 Midden-Europese tijd (UTC+1) een account op Todon.nl aanvragen. Geef ons ajb voldoende tijd om je accountaanvraag te beoordelen.</p>-->
<p>Ga naar <a href="https://joinmastodon.org/servers">joinmastodon.org</a> of <a href="https://fedidb.org/network?s=mastodon">FediDB Network</a> om een andere server te vinden.</p>
<p>It is temporary not possible to request on account on Todon.nl.</p>
<!--<p>You can request an account on Todon.nl between 9h00 and 23h00 Central European Time (UTC+1). Please give us enough time to review your account request.</p>-->
<p>Go to <a href="https://joinmastodon.org/servers">joinmastodon.org</a> or <a href="https://fedidb.org/network?s=mastodon">FediDB Network</a> to find another server.</p>
url:
max_toot_chars: 1312
contact:
email: todon@posteo.eu
account:
id: '1'
username: admin
acct: admin
display_name: "Admin \U0001F913 Todon.nl (mod)"
locked: false
bot: false
discoverable: false
group: false
created_at: '2017-04-28T00:00:00.000Z'
note: "<p>This account is used for \U0001F399 Todon.nl announcements and ⚖️
moderation.</p><p>\U0001F6AB Don&#39;t follow this account when you are not
on Todon.nl.</p><p>New? First read our \U0001F469\U0001F3EB Todon 101 \U0001F469\U0001F393
at <a href=\"https://wiki.todon.eu/todon/101\" target=\"_blank\" rel=\"nofollow
noopener noreferrer\" translate=\"no\"><span class=\"invisible\">https://</span><span
class=\"\">wiki.todon.eu/todon/101</span><span class=\"invisible\"></span></a></p><p>⚖️
For all our moderators go to <a href=\"https://wiki.todon.nl/todon/moderators\"
target=\"_blank\" rel=\"nofollow noopener noreferrer\" translate=\"no\"><span
class=\"invisible\">https://</span><span class=\"\">wiki.todon.nl/todon/moderators</span><span
class=\"invisible\"></span></a></p><p>\U0001F4DD Public toots from this account
are in English.</p><p>\U0001F515 Criticism is fine, but people who do false
accusations are muted. </p><p>✉ todon@posteo.eu</p><p><a href=\"https://todon.nl/tags/nobot\"
class=\"mention hashtag\" rel=\"tag\">#<span>nobot</span></a></p>"
url: https://todon.nl/@admin
uri: https://todon.nl/users/admin
avatar: https://todon.nl/system/accounts/avatars/000/000/001/original/2db61726225ed3e6.png
avatar_static: https://todon.nl/system/accounts/avatars/000/000/001/original/2db61726225ed3e6.png
header: https://todon.nl/system/accounts/headers/000/000/001/original/fb3a846cbc20aa09.png
header_static: https://todon.nl/system/accounts/headers/000/000/001/original/fb3a846cbc20aa09.png
followers_count: 3164
following_count: 8
statuses_count: 724
last_status_at: '2024-01-12'
noindex: true
emojis: []
roles:
- id: '3'
name: Admin
color: "#595aff"
fields:
- name: "\U0001F4DC Terms of Service"
value: <a href="https://wiki.todon.nl/todon/terms_en" target="_blank" rel="nofollow
noopener noreferrer me" translate="no"><span class="invisible">https://</span><span
class="">wiki.todon.nl/todon/terms_en</span><span class="invisible"></span></a>
verified_at: '2018-11-01T14:39:45.465+00:00'
- name: Wiki
value: <a href="https://wiki.todon.nl/todon/information" target="_blank" rel="nofollow
noopener noreferrer me" translate="no"><span class="invisible">https://</span><span
class="ellipsis">wiki.todon.nl/todon/informatio</span><span class="invisible">n</span></a>
verified_at: '2018-11-01T14:40:54.679+00:00'
- name: "\U0001F4CA Status"
value: <a href="https://status.todon.eu" target="_blank" rel="nofollow noopener
noreferrer me" translate="no"><span class="invisible">https://</span><span
class="">status.todon.eu</span><span class="invisible"></span></a>
verified_at: '2023-10-26T20:38:30.185+00:00'
- name: "\U0001F4B3 Donations"
value: <a href="https://wiki.todon.eu/todon/donations" target="_blank" rel="nofollow
noopener noreferrer me" translate="no"><span class="invisible">https://</span><span
class="">wiki.todon.eu/todon/donations</span><span class="invisible"></span></a>
verified_at: '2022-11-02T00:06:31.865+00:00'
rules:
- id: '1'
text: We do not accept racism (in all its forms, incl. hate against Muslims, antisemitism,
apartheid and casteism - see our Terms of Service for our complete definition).
- id: '2'
text: We do not accept hate against lesbians, gays, bisexuals, pansexuals, transgenders,
non-binary people, intersexual people, queer people in general, etc.
- id: '4'
text: Sexism, misogyny and hate against black women (misogynoir).
- id: '6'
text: We do not accept ableism (incl. COVID-19 denial/downplaying and anti-vax)
and body-shaming.
- id: '8'
text: We do not accept harassment and trolling.
- id: '10'
text: We also do not accept other forms of hate speech.
- id: '11'
text: We do not accept (sexual) abuse of minors, adults and animals (also not
virtual).
- id: '13'
text: We do not accept glorification of violence, calls for murder, death threats,
terrorism and militarism.
- id: '15'
text: We do not accept (neo)colonialism (incl. Zionism), imperialism in all forms
and nationalism (above all nationalism of nation states, incl. flags/symbols
of those on Todon.*, see our Terms of Service).
- id: '16'
text: We do not accept fascism, right-wing populism, and right-wing and religious
extremism.
- id: '17'
text: We do not accept evangelisation and other forms of religious propaganda
[local only], and extreme sects and cults.
- id: '19'
text: We do not accept Marxist-Leninists, Stalinists, Maoists or other followers
of extreme authoritarian (so called) communist/socialist ideologies/regimes
(aka tankies).
- id: '20'
text: We do not accept capitalists, including so called 'anarcho-capitalists'
(aka ancaps) and neoliberals.
- id: '21'
text: We do not accept anthropogenic climate change denial, downplaying the climate
crisis, greenwashing and deceptive climate solutions (like nuclear energy).
- id: '27'
text: We do not accept (right-wing) conspiracy 'theories', hoaxes, fake news and
other forms of disinformation.
- id: '28'
text: Another rule in our terms of service at wiki.todon.eu/todon/terms_en. Explain
in the final step.
- uri: mastodon.mauve.moe
title: Mauvestodon
short_description: Escape ship from centralized social media run by Mauve.
description: Chat about random techie and anarchist stuff.
email: contact@mauve.moe
version: 3.5.10
urls:
streaming_api: wss://mastodon.mauve.moe
stats:
user_count: 12
status_count: 3287
domain_count: 11625
thumbnail: https://mastodon.mauve.moe/system/site_uploads/files/000/000/001/original/mauvesoftwareinc.png
languages:
- en
registrations: false
approval_required: false
invites_enabled: true
configuration:
statuses:
max_characters: 500
max_media_attachments: 4
characters_reserved_per_url: 23
media_attachments:
supported_mime_types:
- image/jpeg
- image/png
- image/gif
- video/webm
- video/mp4
- video/quicktime
- video/ogg
- audio/wave
- audio/wav
- audio/x-wav
- audio/x-pn-wave
- audio/ogg
- audio/vorbis
- audio/mpeg
- audio/mp3
- audio/webm
- audio/flac
- audio/aac
- audio/m4a
- audio/x-m4a
- audio/mp4
- audio/3gpp
- video/x-ms-asf
image_size_limit: 10485760
image_matrix_limit: 16777216
video_size_limit: 41943040
video_frame_rate_limit: 60
video_matrix_limit: 2304000
polls:
max_options: 4
max_characters_per_option: 50
min_expiration: 300
max_expiration: 2629746
contact_account:
id: '1'
username: admin
acct: admin
display_name: ''
locked: false
bot: false
discoverable: true
group: false
created_at: '2022-04-25T00:00:00.000Z'
note: ''
url: https://mastodon.mauve.moe/@admin
avatar: https://mastodon.mauve.moe/system/accounts/avatars/000/000/001/original/8c21e71667b48a95.png
avatar_static: https://mastodon.mauve.moe/system/accounts/avatars/000/000/001/original/8c21e71667b48a95.png
header: https://mastodon.mauve.moe/headers/original/missing.png
header_static: https://mastodon.mauve.moe/headers/original/missing.png
followers_count: 0
following_count: 0
statuses_count: 0
last_status_at: '2023-01-30'
emojis: []
fields:
- name: Alternatel Contact
value: <span class="h-card"><a href="https://mastodon.mauve.moe/@mauve" class="u-url
mention">@<span>mauve</span></a></span>
verified_at:
rules: []

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,106 @@
---
"@context":
- https://www.w3.org/ns/activitystreams
- https://w3id.org/security/v1
- manuallyApprovesFollowers: as:manuallyApprovesFollowers
toot: http://joinmastodon.org/ns#
featured:
"@id": toot:featured
"@type": "@id"
featuredTags:
"@id": toot:featuredTags
"@type": "@id"
alsoKnownAs:
"@id": as:alsoKnownAs
"@type": "@id"
movedTo:
"@id": as:movedTo
"@type": "@id"
schema: http://schema.org#
PropertyValue: schema:PropertyValue
value: schema:value
discoverable: toot:discoverable
Device: toot:Device
Ed25519Signature: toot:Ed25519Signature
Ed25519Key: toot:Ed25519Key
Curve25519Key: toot:Curve25519Key
EncryptedMessage: toot:EncryptedMessage
publicKeyBase64: toot:publicKeyBase64
deviceId: toot:deviceId
claim:
"@type": "@id"
"@id": toot:claim
fingerprintKey:
"@type": "@id"
"@id": toot:fingerprintKey
identityKey:
"@type": "@id"
"@id": toot:identityKey
devices:
"@type": "@id"
"@id": toot:devices
messageFranking: toot:messageFranking
messageType: toot:messageType
cipherText: toot:cipherText
suspended: toot:suspended
focalPoint:
"@container": "@list"
"@id": toot:focalPoint
id: https://mastodon.mauve.moe/users/mauve
type: Person
following: https://mastodon.mauve.moe/users/mauve/following
followers: https://mastodon.mauve.moe/users/mauve/followers
inbox: https://mastodon.mauve.moe/users/mauve/inbox
outbox: https://mastodon.mauve.moe/users/mauve/outbox
featured: https://mastodon.mauve.moe/users/mauve/collections/featured
featuredTags: https://mastodon.mauve.moe/users/mauve/collections/tags
preferredUsername: mauve
name: "Mauve \U0001F441\U0001F49C"
summary: "<p>Occult Enby that&#39;s making local-first software with peer to peer
protocols, mesh networks, and the web.</p><p>Also exploring what a local-first
cyberspace might look like in my spare time.</p>"
url: https://mastodon.mauve.moe/@mauve
manuallyApprovesFollowers: false
discoverable: true
published: '2022-04-25T00:00:00Z'
devices: https://mastodon.mauve.moe/users/mauve/collections/devices
alsoKnownAs:
- https://infosec.exchange/users/RangerMauve
publicKey:
id: https://mastodon.mauve.moe/users/mauve#main-key
owner: https://mastodon.mauve.moe/users/mauve
publicKeyPem: |
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxjxu6bRQOjH4caQu7JgZ
umIWFeX0ZdbVnofElev2d9JByqcDoWhmaks3RYdW71RDPNrr0JxqZvUbIw9kQBng
7iQ9YTcXTdJ/N9CQoB22msffYkEIw4ilehCDXdchNs4aoVAUwI8IhkM0p/itz6gK
75C3CQv74Y7rHUJC8ob2p4KUwRUyhgzyhp8QWwCAn/RZ28wP8EbjWF9IskMRo9vq
WUX+Io6hpADRkSwZGoOSW2zxCEBVco6tRmABTte8I0WcAucLyMEyfGMlUvxRew4D
zAWoEBS8SyqM68vUabbZYLns6kya34tvsf1NkvajDGrfgU3D0LlGX++tOa6N9Pkf
XwIDAQAB
-----END PUBLIC KEY-----
tag: []
attachment:
- type: PropertyValue
name: Pronouns
value: they/them/it
- type: PropertyValue
name: Email
value: mauve@mauve.moe
- type: PropertyValue
name: Matrix
value: <span class="h-card"><a href="https://mastodon.mauve.moe/@mauve" class="u-url
mention">@<span>mauve</span></a></span>:mauve.moe
- type: PropertyValue
name: Github/Twitter
value: "@RangerMauve"
endpoints:
sharedInbox: https://mastodon.mauve.moe/inbox
icon:
type: Image
mediaType: image/png
url: https://mastodon.mauve.moe/system/accounts/avatars/000/000/002/original/e4b910cee121b1b8.png
image:
type: Image
mediaType: image/png
url: https://mastodon.mauve.moe/system/accounts/headers/000/000/002/original/a96f990025091662.png

View file

@ -13,7 +13,7 @@
"@rails/activestorage": "^6.1.3-1", "@rails/activestorage": "^6.1.3-1",
"@rails/ujs": "^6.1.3-1", "@rails/ujs": "^6.1.3-1",
"@rails/webpacker": "5.4.4", "@rails/webpacker": "5.4.4",
"@suttyweb/editor": "^0.1.25", "@suttyweb/editor": "^0.1.27",
"babel-loader": "^8.2.2", "babel-loader": "^8.2.2",
"chart.js": "^3.5.1", "chart.js": "^3.5.1",
"chartkick": "^4.0.5", "chartkick": "^4.0.5",
@ -21,6 +21,7 @@
"commonmark": "^0.29.0", "commonmark": "^0.29.0",
"fork-awesome": "^1.1.7", "fork-awesome": "^1.1.7",
"fork-ts-checker-webpack-plugin": "^6.1.0", "fork-ts-checker-webpack-plugin": "^6.1.0",
"htmx.org": "^1.9.11",
"input-map": "git+https://0xacab.org/sutty/input-map.git", "input-map": "git+https://0xacab.org/sutty/input-map.git",
"input-tag": "git+https://0xacab.org/sutty/input-tag.git", "input-tag": "git+https://0xacab.org/sutty/input-tag.git",
"leaflet": "^1.7.1", "leaflet": "^1.7.1",

View file

@ -1821,6 +1821,26 @@
resolved "https://registry.npmjs.org/@csstools/convert-colors/-/convert-colors-1.4.0.tgz" resolved "https://registry.npmjs.org/@csstools/convert-colors/-/convert-colors-1.4.0.tgz"
integrity sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw== integrity sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw==
"@floating-ui/core@^1.0.0":
version "1.6.0"
resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.0.tgz#fa41b87812a16bf123122bf945946bae3fdf7fc1"
integrity sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g==
dependencies:
"@floating-ui/utils" "^0.2.1"
"@floating-ui/dom@^1.5.1":
version "1.6.3"
resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.3.tgz#954e46c1dd3ad48e49db9ada7218b0985cee75ef"
integrity sha512-RnDthu3mzPlQ31Ss/BTwQ1zjzIhr3lk1gZB1OC56h/1vEtaXkESrOqL5fQVMfXpwGtRwX+YsZBdyHtJMQnkArw==
dependencies:
"@floating-ui/core" "^1.0.0"
"@floating-ui/utils" "^0.2.0"
"@floating-ui/utils@^0.2.0", "@floating-ui/utils@^0.2.1":
version "0.2.1"
resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.1.tgz#16308cea045f0fc777b6ff20a9f25474dd8293d2"
integrity sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==
"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": "@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2":
version "0.3.3" version "0.3.3"
resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098"
@ -1955,11 +1975,13 @@
resolved "https://registry.npmjs.org/@stimulus/webpack-helpers/-/webpack-helpers-1.1.1.tgz" resolved "https://registry.npmjs.org/@stimulus/webpack-helpers/-/webpack-helpers-1.1.1.tgz"
integrity sha512-XOkqSw53N9072FLHvpLM25PIwy+ndkSSbnTtjKuyzsv8K5yfkFB2rv68jU1pzqYa9FZLcvZWP4yazC0V38dx9A== integrity sha512-XOkqSw53N9072FLHvpLM25PIwy+ndkSSbnTtjKuyzsv8K5yfkFB2rv68jU1pzqYa9FZLcvZWP4yazC0V38dx9A==
"@suttyweb/editor@^0.1.25": "@suttyweb/editor@^0.1.27":
version "0.1.25" version "0.1.27"
resolved "https://registry.yarnpkg.com/@suttyweb/editor/-/editor-0.1.25.tgz#37b38560642a49b24383473543c28be943695f9f" resolved "https://registry.yarnpkg.com/@suttyweb/editor/-/editor-0.1.27.tgz#9415a0b767e72dbe4fbf42ce87e62fb8f5125c31"
integrity sha512-fxOO9LpdntWzgNZch4cZB6QL0u+jEw0NqsNahKcGBbiJaS0GNGLRrT2LUd/Djc6O8HWkQguPLcquVT5eHq2h9g== integrity sha512-Ts9TZtGiRIaHm+ffVBRl+/nuVcANWZNtFsrGacoajgEsagaIyA1cq8qjiNpPoM5ne9vTba3cAaLP04V/uEIhBw==
dependencies: dependencies:
"@floating-ui/dom" "^1.5.1"
linkifyjs "^4.1.1"
prosemirror-svelte-nodeview "^1.0.2" prosemirror-svelte-nodeview "^1.0.2"
"@types/caseless@*": "@types/caseless@*":
@ -4548,6 +4570,11 @@ html-entities@^1.3.1:
resolved "https://registry.npmjs.org/html-entities/-/html-entities-1.4.0.tgz" resolved "https://registry.npmjs.org/html-entities/-/html-entities-1.4.0.tgz"
integrity sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA== integrity sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA==
htmx.org@^1.9.11:
version "1.9.11"
resolved "https://registry.yarnpkg.com/htmx.org/-/htmx.org-1.9.11.tgz#00192041ee682d6ca7146d0fbd901169ffe72d87"
integrity sha512-WlVuICn8dfNOOgYmdYzYG8zSnP3++AdHkMHooQAzGZObWpVXYathpz/I37ycF4zikR6YduzfCvEcxk20JkIUsw==
http-deceiver@^1.2.7: http-deceiver@^1.2.7:
version "1.2.7" version "1.2.7"
resolved "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz" resolved "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz"
@ -5190,6 +5217,11 @@ linkify-it@^2.0.0:
dependencies: dependencies:
uc.micro "^1.0.1" uc.micro "^1.0.1"
linkifyjs@^4.1.1:
version "4.1.3"
resolved "https://registry.yarnpkg.com/linkifyjs/-/linkifyjs-4.1.3.tgz#0edbc346428a7390a23ea2e5939f76112c9ae07f"
integrity sha512-auMesunaJ8yfkHvK4gfg1K0SaKX/6Wn9g2Aac/NwX+l5VdmFZzo/hdPGxEOETj+ryRa4/fiOPjeeKURSAJx1sg==
loader-runner@^2.4.0: loader-runner@^2.4.0:
version "2.4.0" version "2.4.0"
resolved "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz" resolved "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz"