mirror of https://github.com/LemmyNet/lemmy
Merge branch 'master' into federation
commit
f9443dfbd3
@ -1,3 +1,4 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
patreon: dessalines
|
||||
liberapay: Lemmy
|
||||
|
@ -1 +1 @@
|
||||
v0.6.11
|
||||
v0.6.25
|
||||
|
@ -0,0 +1,283 @@
|
||||
(function() {
|
||||
var config = {
|
||||
|
||||
// Specify a path for custom plugins. Custom plugins will override core plugins.
|
||||
// CUSTOM_PLUGINS_PATH: __dirname + '/yourcustom-plugin-folder',
|
||||
|
||||
DEBUG: false,
|
||||
RICH_LOG_ENABLED: false,
|
||||
|
||||
// For embeds that require render, baseAppUrl will be used as the host.
|
||||
baseAppUrl: "http://yourdomain.com",
|
||||
relativeStaticUrl: "/r",
|
||||
|
||||
// Or just skip built-in renders altogether
|
||||
SKIP_IFRAMELY_RENDERS: true,
|
||||
|
||||
// For legacy reasons the response format of Iframely open-source is
|
||||
// different by default as it does not group the links array by rel.
|
||||
// In order to get the same grouped response as in Cloud API,
|
||||
// add `&group=true` to your request to change response per request
|
||||
// or set `GROUP_LINKS` in your config to `true` for a global change.
|
||||
GROUP_LINKS: true,
|
||||
|
||||
// Number of maximum redirects to follow before aborting the page
|
||||
// request with `redirect loop` error.
|
||||
MAX_REDIRECTS: 4,
|
||||
|
||||
SKIP_OEMBED_RE_LIST: [
|
||||
// /^https?:\/\/yourdomain\.com\//,
|
||||
],
|
||||
|
||||
/*
|
||||
// Used to pass parameters to the generate functions when creating HTML elements
|
||||
// disableSizeWrapper: Don't wrap element (iframe, video, etc) in a positioned div
|
||||
GENERATE_LINK_PARAMS: {
|
||||
disableSizeWrapper: true
|
||||
},
|
||||
*/
|
||||
|
||||
port: 8061, //can be overridden by PORT env var
|
||||
host: '0.0.0.0', // Dockers beware. See https://github.com/itteco/iframely/issues/132#issuecomment-242991246
|
||||
//can be overridden by HOST env var
|
||||
|
||||
// Optional SSL cert, if you serve under HTTPS.
|
||||
/*
|
||||
ssl: {
|
||||
key: require('fs').readFileSync(__dirname + '/key.pem'),
|
||||
cert: require('fs').readFileSync(__dirname + '/cert.pem'),
|
||||
port: 443
|
||||
},
|
||||
*/
|
||||
|
||||
/*
|
||||
Supported cache engines:
|
||||
- no-cache - no caching will be used.
|
||||
- node-cache - good for debug, node memory will be used (https://github.com/tcs-de/nodecache).
|
||||
- redis - https://github.com/mranney/node_redis.
|
||||
- memcached - https://github.com/3rd-Eden/node-memcached
|
||||
*/
|
||||
CACHE_ENGINE: 'node-cache',
|
||||
CACHE_TTL: 0, // In seconds.
|
||||
// 0 = 'never expire' for memcached & node-cache to let cache engine decide itself when to evict the record
|
||||
// 0 = 'no cache' for redis. Use high enough (e.g. 365*24*60*60*1000) ttl for similar 'never expire' approach instead
|
||||
|
||||
/*
|
||||
// Redis cache options.
|
||||
REDIS_OPTIONS: {
|
||||
host: '127.0.0.1',
|
||||
port: 6379
|
||||
},
|
||||
*/
|
||||
|
||||
/*
|
||||
// Memcached options. See https://github.com/3rd-Eden/node-memcached#server-locations
|
||||
MEMCACHED_OPTIONS: {
|
||||
locations: "127.0.0.1:11211"
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
// Access-Control-Allow-Origin list.
|
||||
allowedOrigins: [
|
||||
"*",
|
||||
"http://another_domain.com"
|
||||
],
|
||||
*/
|
||||
|
||||
/*
|
||||
// Uncomment to enable plugin testing framework.
|
||||
tests: {
|
||||
mongodb: 'mongodb://localhost:27017/iframely-tests',
|
||||
single_test_timeout: 10 * 1000,
|
||||
plugin_test_period: 2 * 60 * 60 * 1000,
|
||||
relaunch_script_period: 5 * 60 * 1000
|
||||
},
|
||||
*/
|
||||
|
||||
// If there's no response from remote server, the timeout will occur after
|
||||
RESPONSE_TIMEOUT: 5 * 1000, //ms
|
||||
|
||||
/* From v1.4.0, Iframely supports HTTP/2 by default. Disable it, if you'd rather not.
|
||||
Alternatively, you can also disable per origin. See `proxy` option below.
|
||||
*/
|
||||
// DISABLE_HTTP2: true,
|
||||
|
||||
// Customize API calls to oembed endpoints.
|
||||
ADD_OEMBED_PARAMS: [{
|
||||
// Endpoint url regexp array.
|
||||
re: [/^http:\/\/api\.instagram\.com\/oembed/],
|
||||
// Custom get params object.
|
||||
params: {
|
||||
hidecaption: true
|
||||
}
|
||||
}, {
|
||||
re: [/^https:\/\/www\.facebook\.com\/plugins\/page\/oembed\.json/i],
|
||||
params: {
|
||||
show_posts: 0,
|
||||
show_facepile: 0,
|
||||
maxwidth: 600
|
||||
}
|
||||
}, {
|
||||
// match i=user or i=moment or i=timeline to configure these types invidually
|
||||
// see params spec at https://dev.twitter.com/web/embedded-timelines/oembed
|
||||
re: [/^https?:\/\/publish\.twitter\.com\/oembed\?i=user/i],
|
||||
params: {
|
||||
limit: 1,
|
||||
maxwidth: 600
|
||||
}
|
||||
/*
|
||||
}, {
|
||||
// Facebook https://developers.facebook.com/docs/plugins/oembed-endpoints
|
||||
re: [/^https:\/\/www\.facebook\.com\/plugins\/\w+\/oembed\.json/i],
|
||||
params: {
|
||||
// Skip script tag and fb-root div.
|
||||
omitscript: true
|
||||
}
|
||||
*/
|
||||
}],
|
||||
|
||||
/*
|
||||
// Configure use of HTTP proxies as needed.
|
||||
// You don't have to specify all options per regex - just what you need to override
|
||||
PROXY: [{
|
||||
re: [/^https?:\/\/www\.domain\.com/],
|
||||
proxy_server: 'http://1.2.3.4:8080',
|
||||
user_agent: 'CHANGE YOUR AGENT',
|
||||
headers: {
|
||||
// HTTP headers
|
||||
// Overrides previous params if overlapped.
|
||||
},
|
||||
request_options: {
|
||||
// Refer to: https://github.com/request/request
|
||||
// Overrides previous params if overlapped.
|
||||
},
|
||||
disable_http2: true
|
||||
}],
|
||||
*/
|
||||
|
||||
// Customize API calls to 3rd parties. At the very least - configure required keys.
|
||||
providerOptions: {
|
||||
locale: "en_US", // ISO 639-1 two-letter language code, e.g. en_CA or fr_CH.
|
||||
// Will be added as highest priotity in accept-language header with each request.
|
||||
// Plus is used in FB, YouTube and perhaps other plugins
|
||||
"twitter": {
|
||||
"max-width": 550,
|
||||
"min-width": 250,
|
||||
hide_media: false,
|
||||
hide_thread: false,
|
||||
omit_script: false,
|
||||
center: false,
|
||||
// dnt: true,
|
||||
cache_ttl: 100 * 365 * 24 * 3600 // 100 Years.
|
||||
},
|
||||
readability: {
|
||||
enabled: false
|
||||
// allowPTagDescription: true // to enable description fallback to first paragraph
|
||||
},
|
||||
images: {
|
||||
loadSize: false, // if true, will try an load first bytes of all images to get/confirm the sizes
|
||||
checkFavicon: false // if true, will verify all favicons
|
||||
},
|
||||
tumblr: {
|
||||
consumer_key: "INSERT YOUR VALUE"
|
||||
// media_only: true // disables status embeds for images and videos - will return plain media
|
||||
},
|
||||
google: {
|
||||
// https://developers.google.com/maps/documentation/embed/guide#api_key
|
||||
maps_key: "INSERT YOUR VALUE"
|
||||
},
|
||||
|
||||
/*
|
||||
// Optional Camo Proxy to wrap all images: https://github.com/atmos/camo
|
||||
camoProxy: {
|
||||
camo_proxy_key: "INSERT YOUR VALUE",
|
||||
camo_proxy_host: "INSERT YOUR VALUE"
|
||||
// ssl_only: true // will only proxy non-ssl images
|
||||
},
|
||||
*/
|
||||
|
||||
// List of query parameters to add to YouTube and Vimeo frames
|
||||
// Start it with leading "?". Or omit alltogether for default values
|
||||
// API key is optional, youtube will work without it too.
|
||||
// It is probably the same API key you use for Google Maps.
|
||||
youtube: {
|
||||
// api_key: "INSERT YOUR VALUE",
|
||||
get_params: "?rel=0&showinfo=1" // https://developers.google.com/youtube/player_parameters
|
||||
},
|
||||
vimeo: {
|
||||
get_params: "?byline=0&badge=0" // https://developer.vimeo.com/player/embedding
|
||||
},
|
||||
|
||||
/*
|
||||
soundcloud: {
|
||||
old_player: true // enables classic player
|
||||
},
|
||||
giphy: {
|
||||
media_only: true // disables branded player for gifs and returns just the image
|
||||
}
|
||||
*/
|
||||
/*
|
||||
bandcamp: {
|
||||
get_params: '/size=large/bgcol=333333/linkcol=ffffff/artwork=small/transparent=true/',
|
||||
media: {
|
||||
album: {
|
||||
height: 472,
|
||||
'max-width': 700
|
||||
},
|
||||
track: {
|
||||
height: 120,
|
||||
'max-width': 700
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
},
|
||||
|
||||
// WHITELIST_WILDCARD, if present, will be added to whitelist as record for top level domain: "*"
|
||||
// with it, you can define what parsers do when they run accross unknown publisher.
|
||||
// If absent or empty, all generic media parsers will be disabled except for known domains
|
||||
// More about format: https://iframely.com/docs/qa-format
|
||||
|
||||
/*
|
||||
WHITELIST_WILDCARD: {
|
||||
"twitter": {
|
||||
"player": "allow",
|
||||
"photo": "deny"
|
||||
},
|
||||
"oembed": {
|
||||
"video": "allow",
|
||||
"photo": "allow",
|
||||
"rich": "deny",
|
||||
"link": "deny"
|
||||
},
|
||||
"og": {
|
||||
"video": ["allow", "ssl", "responsive"]
|
||||
},
|
||||
"iframely": {
|
||||
"survey": "allow",
|
||||
"reader": "allow",
|
||||
"player": "allow",
|
||||
"image": "allow"
|
||||
},
|
||||
"html-meta": {
|
||||
"video": ["allow", "responsive"],
|
||||
"promo": "allow"
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Black-list any of the inappropriate domains. Iframely will return 417
|
||||
// At minimum, keep your localhosts blacklisted to avoid SSRF
|
||||
BLACKLIST_DOMAINS_RE: [
|
||||
/^https?:\/\/127\.0\.0\.1/i,
|
||||
/^https?:\/\/localhost/i,
|
||||
|
||||
// And this is AWS metadata service
|
||||
// https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html
|
||||
/^https?:\/\/169\.254\.169\.254/
|
||||
]
|
||||
};
|
||||
|
||||
module.exports = config;
|
||||
})();
|
@ -0,0 +1,28 @@
|
||||
# Lemmy Guide
|
||||
|
||||
Start typing...
|
||||
|
||||
- `@a_user_name` to get a list of usernames.
|
||||
- `#a_community` to get a list of communities.
|
||||
- `:emoji` to get a list of emojis.
|
||||
|
||||
## Markdown Guide
|
||||
|
||||
Type | Or | … to Get
|
||||
--- | --- | ---
|
||||
\*Italic\* | \_Italic\_ | _Italic_
|
||||
\*\*Bold\*\* | \_\_Bold\_\_ | **Bold**
|
||||
\# Heading 1 | Heading 1 <br> ========= | <h4>Heading 1</h4>
|
||||
\## Heading 2 | Heading 2 <br>--------- | <h5>Heading 2</h5>
|
||||
\[Link\](http://a.com) | \[Link\]\[1\]<br>⋮ <br>\[1\]: http://b.org | [Link](https://commonmark.org/)
|
||||
!\[Image\](http://url/a.png) | !\[Image\]\[1\]<br>⋮ <br>\[1\]: http://url/b.jpg | ![Markdown](https://commonmark.org/help/images/favicon.png)
|
||||
\> Blockquote | | <blockquote>Blockquote</blockquote>
|
||||
\* List <br>\* List <br>\* List | \- List <br>\- List <br>\- List <br> | * List <br>* List <br>* List <br>
|
||||
1\. One <br>2\. Two <br>3\. Three | 1) One<br>2) Two<br>3) Three | 1. One<br>2. Two<br>3. Three
|
||||
Horizontal Rule <br>\--- | Horizontal Rule<br>\*\*\* | Horizontal Rule <br><hr>
|
||||
\`Inline code\` with backticks | |`Inline code` with backticks
|
||||
\`\`\`<br>\# code block <br>print '3 backticks or'<br>print 'indent 4 spaces' <br>\`\`\` | ····\# code block<br>····print '3 backticks or'<br>····print 'indent 4 spaces' | \# code block <br>print '3 backticks or'<br>print 'indent 4 spaces'
|
||||
::: spoiler hidden or nsfw stuff<br>*a bunch of spoilers here*<br>::: | | <details><summary> hidden or nsfw stuff </summary><p><em>a bunch of spoilers here</em></p></details>
|
||||
|
||||
[CommonMark Tutorial](https://commonmark.org/help/tutorial/)
|
||||
|
@ -1 +1,3 @@
|
||||
Information for Lemmy instance admins, and those who want to start an instance.
|
||||
# Admin info
|
||||
|
||||
Information for Lemmy instance admins, and those who want to start an instance.
|
||||
|
@ -1,6 +1,15 @@
|
||||
# Configuration
|
||||
|
||||
The configuration is based on the file [defaults.hjson](server/config/defaults.hjson). This file also contains documentation for all the available options. To override the defaults, you can copy the options you want to change into your local `config.hjson` file.
|
||||
|
||||
Additionally, you can override any config files with environment variables. These have the same name as the config options, and are prefixed with `LEMMY_`. For example, you can override the `database.password` with
|
||||
`LEMMY__DATABASE__POOL_SIZE=10`.
|
||||
|
||||
An additional option `LEMMY_DATABASE_URL` is available, which can be used with a PostgreSQL connection string like `postgres://lemmy:password@lemmy_db:5432/lemmy`, passing all connection details at once.
|
||||
|
||||
If the Docker container is not used, manually create the database specified above by running the following commands:
|
||||
|
||||
```bash
|
||||
cd server
|
||||
./db-init.sh
|
||||
```
|
||||
|
@ -0,0 +1,43 @@
|
||||
#!/bin/bash
|
||||
|
||||
username=lemmy
|
||||
dbname=lemmy
|
||||
port=5432
|
||||
|
||||
password=""
|
||||
password_confirm=""
|
||||
password_valid=0
|
||||
|
||||
while [ "$password_valid" == 0 ]
|
||||
do
|
||||
read -p "Enter database password: " -s password
|
||||
echo
|
||||
|
||||
read -p "Verify database password: " -s password_confirm
|
||||
echo
|
||||
echo
|
||||
|
||||
# Start the loop from the top if either check fails
|
||||
if [ -z "$password" ]
|
||||
then
|
||||
echo "Error: Password cannot be empty." 1>&2
|
||||
echo
|
||||
continue
|
||||
fi
|
||||
if [ "$password" != "$password_confirm" ]
|
||||
then
|
||||
echo "Error: Passwords don't match." 1>&2
|
||||
echo
|
||||
continue
|
||||
fi
|
||||
|
||||
# Set the password_valid variable to break out of the loop
|
||||
password_valid=1
|
||||
done
|
||||
|
||||
|
||||
psql -c "CREATE USER $username WITH PASSWORD '$password' SUPERUSER;" -U postgres
|
||||
psql -c 'CREATE DATABASE $dbname WITH OWNER $username;' -U postgres
|
||||
export LEMMY_DATABASE_URL=postgres://$username:$password@localhost:$port/$dbname
|
||||
|
||||
echo $LEMMY_DATABASE_URL
|
@ -0,0 +1,132 @@
|
||||
-- Drop the dependent views
|
||||
drop view post_view;
|
||||
drop view post_mview;
|
||||
drop materialized view post_aggregates_mview;
|
||||
drop view post_aggregates_view;
|
||||
drop view mod_remove_post_view;
|
||||
drop view mod_sticky_post_view;
|
||||
drop view mod_lock_post_view;
|
||||
drop view mod_remove_comment_view;
|
||||
|
||||
alter table post alter column name type varchar(100);
|
||||
|
||||
-- regen post view
|
||||
create view post_aggregates_view as
|
||||
select
|
||||
p.*,
|
||||
(select u.banned from user_ u where p.creator_id = u.id) as banned,
|
||||
(select cb.id::bool from community_user_ban cb where p.creator_id = cb.user_id and p.community_id = cb.community_id) as banned_from_community,
|
||||
(select name from user_ where p.creator_id = user_.id) as creator_name,
|
||||
(select avatar from user_ where p.creator_id = user_.id) as creator_avatar,
|
||||
(select name from community where p.community_id = community.id) as community_name,
|
||||
(select removed from community c where p.community_id = c.id) as community_removed,
|
||||
(select deleted from community c where p.community_id = c.id) as community_deleted,
|
||||
(select nsfw from community c where p.community_id = c.id) as community_nsfw,
|
||||
(select count(*) from comment where comment.post_id = p.id) as number_of_comments,
|
||||
coalesce(sum(pl.score), 0) as score,
|
||||
count (case when pl.score = 1 then 1 else null end) as upvotes,
|
||||
count (case when pl.score = -1 then 1 else null end) as downvotes,
|
||||
hot_rank(coalesce(sum(pl.score) , 0), p.published) as hot_rank
|
||||
from post p
|
||||
left join post_like pl on p.id = pl.post_id
|
||||
group by p.id;
|
||||
|
||||
create materialized view post_aggregates_mview as select * from post_aggregates_view;
|
||||
|
||||
create unique index idx_post_aggregates_mview_id on post_aggregates_mview (id);
|
||||
|
||||
create view post_view as
|
||||
with all_post as (
|
||||
select
|
||||
pa.*
|
||||
from post_aggregates_view pa
|
||||
)
|
||||
select
|
||||
ap.*,
|
||||
u.id as user_id,
|
||||
coalesce(pl.score, 0) as my_vote,
|
||||
(select cf.id::bool from community_follower cf where u.id = cf.user_id and cf.community_id = ap.community_id) as subscribed,
|
||||
(select pr.id::bool from post_read pr where u.id = pr.user_id and pr.post_id = ap.id) as read,
|
||||
(select ps.id::bool from post_saved ps where u.id = ps.user_id and ps.post_id = ap.id) as saved
|
||||
from user_ u
|
||||
cross join all_post ap
|
||||
left join post_like pl on u.id = pl.user_id and ap.id = pl.post_id
|
||||
|
||||
union all
|
||||
|
||||
select
|
||||
ap.*,
|
||||
null as user_id,
|
||||
null as my_vote,
|
||||
null as subscribed,
|
||||
null as read,
|
||||
null as saved
|
||||
from all_post ap
|
||||
;
|
||||
|
||||
create view post_mview as
|
||||
with all_post as (
|
||||
select
|
||||
pa.*
|
||||
from post_aggregates_mview pa
|
||||
)
|
||||
select
|
||||
ap.*,
|
||||
u.id as user_id,
|
||||
coalesce(pl.score, 0) as my_vote,
|
||||
(select cf.id::bool from community_follower cf where u.id = cf.user_id and cf.community_id = ap.community_id) as subscribed,
|
||||
(select pr.id::bool from post_read pr where u.id = pr.user_id and pr.post_id = ap.id) as read,
|
||||
(select ps.id::bool from post_saved ps where u.id = ps.user_id and ps.post_id = ap.id) as saved
|
||||
from user_ u
|
||||
cross join all_post ap
|
||||
left join post_like pl on u.id = pl.user_id and ap.id = pl.post_id
|
||||
|
||||
union all
|
||||
|
||||
select
|
||||
ap.*,
|
||||
null as user_id,
|
||||
null as my_vote,
|
||||
null as subscribed,
|
||||
null as read,
|
||||
null as saved
|
||||
from all_post ap
|
||||
;
|
||||
|
||||
-- The mod views
|
||||
|
||||
create view mod_remove_post_view as
|
||||
select mrp.*,
|
||||
(select name from user_ u where mrp.mod_user_id = u.id) as mod_user_name,
|
||||
(select name from post p where mrp.post_id = p.id) as post_name,
|
||||
(select c.id from post p, community c where mrp.post_id = p.id and p.community_id = c.id) as community_id,
|
||||
(select c.name from post p, community c where mrp.post_id = p.id and p.community_id = c.id) as community_name
|
||||
from mod_remove_post mrp;
|
||||
|
||||
create view mod_lock_post_view as
|
||||
select mlp.*,
|
||||
(select name from user_ u where mlp.mod_user_id = u.id) as mod_user_name,
|
||||
(select name from post p where mlp.post_id = p.id) as post_name,
|
||||
(select c.id from post p, community c where mlp.post_id = p.id and p.community_id = c.id) as community_id,
|
||||
(select c.name from post p, community c where mlp.post_id = p.id and p.community_id = c.id) as community_name
|
||||
from mod_lock_post mlp;
|
||||
|
||||
create view mod_remove_comment_view as
|
||||
select mrc.*,
|
||||
(select name from user_ u where mrc.mod_user_id = u.id) as mod_user_name,
|
||||
(select c.id from comment c where mrc.comment_id = c.id) as comment_user_id,
|
||||
(select name from user_ u, comment c where mrc.comment_id = c.id and u.id = c.creator_id) as comment_user_name,
|
||||
(select content from comment c where mrc.comment_id = c.id) as comment_content,
|
||||
(select p.id from post p, comment c where mrc.comment_id = c.id and c.post_id = p.id) as post_id,
|
||||
(select p.name from post p, comment c where mrc.comment_id = c.id and c.post_id = p.id) as post_name,
|
||||
(select co.id from comment c, post p, community co where mrc.comment_id = c.id and c.post_id = p.id and p.community_id = co.id) as community_id,
|
||||
(select co.name from comment c, post p, community co where mrc.comment_id = c.id and c.post_id = p.id and p.community_id = co.id) as community_name
|
||||
from mod_remove_comment mrc;
|
||||
|
||||
create view mod_sticky_post_view as
|
||||
select msp.*,
|
||||
(select name from user_ u where msp.mod_user_id = u.id) as mod_user_name,
|
||||
(select name from post p where msp.post_id = p.id) as post_name,
|
||||
(select c.id from post p, community c where msp.post_id = p.id and p.community_id = c.id) as community_id,
|
||||
(select c.name from post p, community c where msp.post_id = p.id and p.community_id = c.id) as community_name
|
||||
from mod_sticky_post msp;
|
@ -0,0 +1,133 @@
|
||||
-- Drop the dependent views
|
||||
drop view post_view;
|
||||
drop view post_mview;
|
||||
drop materialized view post_aggregates_mview;
|
||||
drop view post_aggregates_view;
|
||||
drop view mod_remove_post_view;
|
||||
drop view mod_sticky_post_view;
|
||||
drop view mod_lock_post_view;
|
||||
drop view mod_remove_comment_view;
|
||||
|
||||
-- Add the extra post limit
|
||||
alter table post alter column name type varchar(200);
|
||||
|
||||
-- regen post view
|
||||
create view post_aggregates_view as
|
||||
select
|
||||
p.*,
|
||||
(select u.banned from user_ u where p.creator_id = u.id) as banned,
|
||||
(select cb.id::bool from community_user_ban cb where p.creator_id = cb.user_id and p.community_id = cb.community_id) as banned_from_community,
|
||||
(select name from user_ where p.creator_id = user_.id) as creator_name,
|
||||
(select avatar from user_ where p.creator_id = user_.id) as creator_avatar,
|
||||
(select name from community where p.community_id = community.id) as community_name,
|
||||
(select removed from community c where p.community_id = c.id) as community_removed,
|
||||
(select deleted from community c where p.community_id = c.id) as community_deleted,
|
||||
(select nsfw from community c where p.community_id = c.id) as community_nsfw,
|
||||
(select count(*) from comment where comment.post_id = p.id) as number_of_comments,
|
||||
coalesce(sum(pl.score), 0) as score,
|
||||
count (case when pl.score = 1 then 1 else null end) as upvotes,
|
||||
count (case when pl.score = -1 then 1 else null end) as downvotes,
|
||||
hot_rank(coalesce(sum(pl.score) , 0), p.published) as hot_rank
|
||||
from post p
|
||||
left join post_like pl on p.id = pl.post_id
|
||||
group by p.id;
|
||||
|
||||
create materialized view post_aggregates_mview as select * from post_aggregates_view;
|
||||
|
||||
create unique index idx_post_aggregates_mview_id on post_aggregates_mview (id);
|
||||
|
||||
create view post_view as
|
||||
with all_post as (
|
||||
select
|
||||
pa.*
|
||||
from post_aggregates_view pa
|
||||
)
|
||||
select
|
||||
ap.*,
|
||||
u.id as user_id,
|
||||
coalesce(pl.score, 0) as my_vote,
|
||||
(select cf.id::bool from community_follower cf where u.id = cf.user_id and cf.community_id = ap.community_id) as subscribed,
|
||||
(select pr.id::bool from post_read pr where u.id = pr.user_id and pr.post_id = ap.id) as read,
|
||||
(select ps.id::bool from post_saved ps where u.id = ps.user_id and ps.post_id = ap.id) as saved
|
||||
from user_ u
|
||||
cross join all_post ap
|
||||
left join post_like pl on u.id = pl.user_id and ap.id = pl.post_id
|
||||
|
||||
union all
|
||||
|
||||
select
|
||||
ap.*,
|
||||
null as user_id,
|
||||
null as my_vote,
|
||||
null as subscribed,
|
||||
null as read,
|
||||
null as saved
|
||||
from all_post ap
|
||||
;
|
||||
|
||||
create view post_mview as
|
||||
with all_post as (
|
||||
select
|
||||
pa.*
|
||||
from post_aggregates_mview pa
|
||||
)
|
||||
select
|
||||
ap.*,
|
||||
u.id as user_id,
|
||||
coalesce(pl.score, 0) as my_vote,
|
||||
(select cf.id::bool from community_follower cf where u.id = cf.user_id and cf.community_id = ap.community_id) as subscribed,
|
||||
(select pr.id::bool from post_read pr where u.id = pr.user_id and pr.post_id = ap.id) as read,
|
||||
(select ps.id::bool from post_saved ps where u.id = ps.user_id and ps.post_id = ap.id) as saved
|
||||
from user_ u
|
||||
cross join all_post ap
|
||||
left join post_like pl on u.id = pl.user_id and ap.id = pl.post_id
|
||||
|
||||
union all
|
||||
|
||||
select
|
||||
ap.*,
|
||||
null as user_id,
|
||||
null as my_vote,
|
||||
null as subscribed,
|
||||
null as read,
|
||||
null as saved
|
||||
from all_post ap
|
||||
;
|
||||
|
||||
-- The mod views
|
||||
|
||||
create view mod_remove_post_view as
|
||||
select mrp.*,
|
||||
(select name from user_ u where mrp.mod_user_id = u.id) as mod_user_name,
|
||||
(select name from post p where mrp.post_id = p.id) as post_name,
|
||||
(select c.id from post p, community c where mrp.post_id = p.id and p.community_id = c.id) as community_id,
|
||||
(select c.name from post p, community c where mrp.post_id = p.id and p.community_id = c.id) as community_name
|
||||
from mod_remove_post mrp;
|
||||
|
||||
create view mod_lock_post_view as
|
||||
select mlp.*,
|
||||
(select name from user_ u where mlp.mod_user_id = u.id) as mod_user_name,
|
||||
(select name from post p where mlp.post_id = p.id) as post_name,
|
||||
(select c.id from post p, community c where mlp.post_id = p.id and p.community_id = c.id) as community_id,
|
||||
(select c.name from post p, community c where mlp.post_id = p.id and p.community_id = c.id) as community_name
|
||||
from mod_lock_post mlp;
|
||||
|
||||
create view mod_remove_comment_view as
|
||||
select mrc.*,
|
||||
(select name from user_ u where mrc.mod_user_id = u.id) as mod_user_name,
|
||||
(select c.id from comment c where mrc.comment_id = c.id) as comment_user_id,
|
||||
(select name from user_ u, comment c where mrc.comment_id = c.id and u.id = c.creator_id) as comment_user_name,
|
||||
(select content from comment c where mrc.comment_id = c.id) as comment_content,
|
||||
(select p.id from post p, comment c where mrc.comment_id = c.id and c.post_id = p.id) as post_id,
|
||||
(select p.name from post p, comment c where mrc.comment_id = c.id and c.post_id = p.id) as post_name,
|
||||
(select co.id from comment c, post p, community co where mrc.comment_id = c.id and c.post_id = p.id and p.community_id = co.id) as community_id,
|
||||
(select co.name from comment c, post p, community co where mrc.comment_id = c.id and c.post_id = p.id and p.community_id = co.id) as community_name
|
||||
from mod_remove_comment mrc;
|
||||
|
||||
create view mod_sticky_post_view as
|
||||
select msp.*,
|
||||
(select name from user_ u where msp.mod_user_id = u.id) as mod_user_name,
|
||||
(select name from post p where msp.post_id = p.id) as post_name,
|
||||
(select c.id from post p, community c where msp.post_id = p.id and p.community_id = c.id) as community_id,
|
||||
(select c.name from post p, community c where msp.post_id = p.id and p.community_id = c.id) as community_name
|
||||
from mod_sticky_post msp;
|
@ -0,0 +1,206 @@
|
||||
|
||||
drop view reply_view;
|
||||
drop view user_mention_view;
|
||||
drop view user_mention_mview;
|
||||
drop view comment_view;
|
||||
drop view comment_mview;
|
||||
drop materialized view comment_aggregates_mview;
|
||||
drop view comment_aggregates_view;
|
||||
|
||||
-- reply and comment view
|
||||
create view comment_aggregates_view as
|
||||
select
|
||||
c.*,
|
||||
(select community_id from post p where p.id = c.post_id),
|
||||
(select u.banned from user_ u where c.creator_id = u.id) as banned,
|
||||
(select cb.id::bool from community_user_ban cb, post p where c.creator_id = cb.user_id and p.id = c.post_id and p.community_id = cb.community_id) as banned_from_community,
|
||||
(select name from user_ where c.creator_id = user_.id) as creator_name,
|
||||
(select avatar from user_ where c.creator_id = user_.id) as creator_avatar,
|
||||
coalesce(sum(cl.score), 0) as score,
|
||||
count (case when cl.score = 1 then 1 else null end) as upvotes,
|
||||
count (case when cl.score = -1 then 1 else null end) as downvotes
|
||||
from comment c
|
||||
left join comment_like cl on c.id = cl.comment_id
|
||||
group by c.id;
|
||||
|
||||
create materialized view comment_aggregates_mview as select * from comment_aggregates_view;
|
||||
|
||||
create unique index idx_comment_aggregates_mview_id on comment_aggregates_mview (id);
|
||||
|
||||
create view comment_view as
|
||||
with all_comment as
|
||||
(
|
||||
select
|
||||
ca.*
|
||||
from comment_aggregates_view ca
|
||||
)
|
||||
|
||||
select
|
||||
ac.*,
|
||||
u.id as user_id,
|
||||
coalesce(cl.score, 0) as my_vote,
|
||||
(select cs.id::bool from comment_saved cs where u.id = cs.user_id and cs.comment_id = ac.id) as saved
|
||||
from user_ u
|
||||
cross join all_comment ac
|
||||
left join comment_like cl on u.id = cl.user_id and ac.id = cl.comment_id
|
||||
|
||||
union all
|
||||
|
||||
select
|
||||
ac.*,
|
||||
null as user_id,
|
||||
null as my_vote,
|
||||
null as saved
|
||||
from all_comment ac
|
||||
;
|
||||
|
||||
create view comment_mview as
|
||||
with all_comment as
|
||||
(
|
||||
select
|
||||
ca.*
|
||||
from comment_aggregates_mview ca
|
||||
)
|
||||
|
||||
select
|
||||
ac.*,
|
||||
u.id as user_id,
|
||||
coalesce(cl.score, 0) as my_vote,
|
||||
(select cs.id::bool from comment_saved cs where u.id = cs.user_id and cs.comment_id = ac.id) as saved
|
||||
from user_ u
|
||||
cross join all_comment ac
|
||||
left join comment_like cl on u.id = cl.user_id and ac.id = cl.comment_id
|
||||
|
||||
union all
|
||||
|
||||
select
|
||||
ac.*,
|
||||
null as user_id,
|
||||
null as my_vote,
|
||||
null as saved
|
||||
from all_comment ac
|
||||
;
|
||||
|
||||
|
||||
-- Do the reply_view referencing the comment_mview
|
||||
create view reply_view as
|
||||
with closereply as (
|
||||
select
|
||||
c2.id,
|
||||
c2.creator_id as sender_id,
|
||||
c.creator_id as recipient_id
|
||||
from comment c
|
||||
inner join comment c2 on c.id = c2.parent_id
|
||||
where c2.creator_id != c.creator_id
|
||||
-- Do union where post is null
|
||||
union
|
||||
select
|
||||
c.id,
|
||||
c.creator_id as sender_id,
|
||||
p.creator_id as recipient_id
|
||||
from comment c, post p
|
||||
where c.post_id = p.id and c.parent_id is null and c.creator_id != p.creator_id
|
||||
)
|
||||
select cv.*,
|
||||
closereply.recipient_id
|
||||
from comment_mview cv, closereply
|
||||
where closereply.id = cv.id
|
||||
;
|
||||
|
||||
-- user mention
|
||||
create view user_mention_view as
|
||||
select
|
||||
c.id,
|
||||
um.id as user_mention_id,
|
||||
c.creator_id,
|
||||
c.post_id,
|
||||
c.parent_id,
|
||||
c.content,
|
||||
c.removed,
|
||||
um.read,
|
||||
c.published,
|
||||
c.updated,
|
||||
c.deleted,
|
||||
c.community_id,
|
||||
c.banned,
|
||||
c.banned_from_community,
|
||||
c.creator_name,
|
||||
c.creator_avatar,
|
||||
c.score,
|
||||
c.upvotes,
|
||||
c.downvotes,
|
||||
c.user_id,
|
||||
c.my_vote,
|
||||
c.saved,
|
||||
um.recipient_id
|
||||
from user_mention um, comment_view c
|
||||
where um.comment_id = c.id;
|
||||
|
||||
|
||||
create view user_mention_mview as
|
||||
with all_comment as
|
||||
(
|
||||
select
|
||||
ca.*
|
||||
from comment_aggregates_mview ca
|
||||
)
|
||||
|
||||
select
|
||||
ac.id,
|
||||
um.id as user_mention_id,
|
||||
ac.creator_id,
|
||||
ac.post_id,
|
||||
ac.parent_id,
|
||||
ac.content,
|
||||
ac.removed,
|
||||
um.read,
|
||||
ac.published,
|
||||
ac.updated,
|
||||
ac.deleted,
|
||||
ac.community_id,
|
||||
ac.banned,
|
||||
ac.banned_from_community,
|
||||
ac.creator_name,
|
||||
ac.creator_avatar,
|
||||
ac.score,
|
||||
ac.upvotes,
|
||||
ac.downvotes,
|
||||
u.id as user_id,
|
||||
coalesce(cl.score, 0) as my_vote,
|
||||
(select cs.id::bool from comment_saved cs where u.id = cs.user_id and cs.comment_id = ac.id) as saved,
|
||||
um.recipient_id
|
||||
from user_ u
|
||||
cross join all_comment ac
|
||||
left join comment_like cl on u.id = cl.user_id and ac.id = cl.comment_id
|
||||
left join user_mention um on um.comment_id = ac.id
|
||||
|
||||
union all
|
||||
|
||||
select
|
||||
ac.id,
|
||||
um.id as user_mention_id,
|
||||
ac.creator_id,
|
||||
ac.post_id,
|
||||
ac.parent_id,
|
||||
ac.content,
|
||||
ac.removed,
|
||||
um.read,
|
||||
ac.published,
|
||||
ac.updated,
|
||||
ac.deleted,
|
||||
ac.community_id,
|
||||
ac.banned,
|
||||
ac.banned_from_community,
|
||||
ac.creator_name,
|
||||
ac.creator_avatar,
|
||||
ac.score,
|
||||
ac.upvotes,
|
||||
ac.downvotes,
|
||||
null as user_id,
|
||||
null as my_vote,
|
||||
null as saved,
|
||||
um.recipient_id
|
||||
from all_comment ac
|
||||
left join user_mention um on um.comment_id = ac.id
|
||||
;
|
||||
|
@ -0,0 +1,220 @@
|
||||
|
||||
-- Adding community name, hot_rank, to comment_view, user_mention_view, and subscribed to comment_view
|
||||
|
||||
-- Rebuild the comment view
|
||||
drop view reply_view;
|
||||
drop view user_mention_view;
|
||||
drop view user_mention_mview;
|
||||
drop view comment_view;
|
||||
drop view comment_mview;
|
||||
drop materialized view comment_aggregates_mview;
|
||||
drop view comment_aggregates_view;
|
||||
|
||||
-- reply and comment view
|
||||
create view comment_aggregates_view as
|
||||
select
|
||||
c.*,
|
||||
(select community_id from post p where p.id = c.post_id),
|
||||
(select co.name from post p, community co where p.id = c.post_id and p.community_id = co.id) as community_name,
|
||||
(select u.banned from user_ u where c.creator_id = u.id) as banned,
|
||||
(select cb.id::bool from community_user_ban cb, post p where c.creator_id = cb.user_id and p.id = c.post_id and p.community_id = cb.community_id) as banned_from_community,
|
||||
(select name from user_ where c.creator_id = user_.id) as creator_name,
|
||||
(select avatar from user_ where c.creator_id = user_.id) as creator_avatar,
|
||||
coalesce(sum(cl.score), 0) as score,
|
||||
count (case when cl.score = 1 then 1 else null end) as upvotes,
|
||||
count (case when cl.score = -1 then 1 else null end) as downvotes,
|
||||
hot_rank(coalesce(sum(cl.score) , 0), c.published) as hot_rank
|
||||
from comment c
|
||||
left join comment_like cl on c.id = cl.comment_id
|
||||
group by c.id;
|
||||
|
||||
create materialized view comment_aggregates_mview as select * from comment_aggregates_view;
|
||||
|
||||
create unique index idx_comment_aggregates_mview_id on comment_aggregates_mview (id);
|
||||
|
||||
create view comment_view as
|
||||
with all_comment as
|
||||
(
|
||||
select
|
||||
ca.*
|
||||
from comment_aggregates_view ca
|
||||
)
|
||||
|
||||
select
|
||||
ac.*,
|
||||
u.id as user_id,
|
||||
coalesce(cl.score, 0) as my_vote,
|
||||
(select cf.id::boolean from community_follower cf where u.id = cf.user_id and ac.community_id = cf.community_id) as subscribed,
|
||||
(select cs.id::bool from comment_saved cs where u.id = cs.user_id and cs.comment_id = ac.id) as saved
|
||||
from user_ u
|
||||
cross join all_comment ac
|
||||
left join comment_like cl on u.id = cl.user_id and ac.id = cl.comment_id
|
||||
|
||||
union all
|
||||
|
||||
select
|
||||
ac.*,
|
||||
null as user_id,
|
||||
null as my_vote,
|
||||
null as subscribed,
|
||||
null as saved
|
||||
from all_comment ac
|
||||
;
|
||||
|
||||
create view comment_mview as
|
||||
with all_comment as
|
||||
(
|
||||
select
|
||||
ca.*
|
||||
from comment_aggregates_mview ca
|
||||
)
|
||||
|
||||
select
|
||||
ac.*,
|
||||
u.id as user_id,
|
||||
coalesce(cl.score, 0) as my_vote,
|
||||
(select cf.id::boolean from community_follower cf where u.id = cf.user_id and ac.community_id = cf.community_id) as subscribed,
|
||||
(select cs.id::bool from comment_saved cs where u.id = cs.user_id and cs.comment_id = ac.id) as saved
|
||||
from user_ u
|
||||
cross join all_comment ac
|
||||
left join comment_like cl on u.id = cl.user_id and ac.id = cl.comment_id
|
||||
|
||||
union all
|
||||
|
||||
select
|
||||
ac.*,
|
||||
null as user_id,
|
||||
null as my_vote,
|
||||
null as subscribed,
|
||||
null as saved
|
||||
from all_comment ac
|
||||
;
|
||||
|
||||
-- Do the reply_view referencing the comment_mview
|
||||
create view reply_view as
|
||||
with closereply as (
|
||||
select
|
||||
c2.id,
|
||||
c2.creator_id as sender_id,
|
||||
c.creator_id as recipient_id
|
||||
from comment c
|
||||
inner join comment c2 on c.id = c2.parent_id
|
||||
where c2.creator_id != c.creator_id
|
||||
-- Do union where post is null
|
||||
union
|
||||
select
|
||||
c.id,
|
||||
c.creator_id as sender_id,
|
||||
p.creator_id as recipient_id
|
||||
from comment c, post p
|
||||
where c.post_id = p.id and c.parent_id is null and c.creator_id != p.creator_id
|
||||
)
|
||||
select cv.*,
|
||||
closereply.recipient_id
|
||||
from comment_mview cv, closereply
|
||||
where closereply.id = cv.id
|
||||
;
|
||||
|
||||
-- user mention
|
||||
create view user_mention_view as
|
||||
select
|
||||
c.id,
|
||||
um.id as user_mention_id,
|
||||
c.creator_id,
|
||||
c.post_id,
|
||||
c.parent_id,
|
||||
c.content,
|
||||
c.removed,
|
||||
um.read,
|
||||
c.published,
|
||||
c.updated,
|
||||
c.deleted,
|
||||
c.community_id,
|
||||
c.community_name,
|
||||
c.banned,
|
||||
c.banned_from_community,
|
||||
c.creator_name,
|
||||
c.creator_avatar,
|
||||
c.score,
|
||||
c.upvotes,
|
||||
c.downvotes,
|
||||
c.hot_rank,
|
||||
c.user_id,
|
||||
c.my_vote,
|
||||
c.saved,
|
||||
um.recipient_id
|
||||
from user_mention um, comment_view c
|
||||
where um.comment_id = c.id;
|
||||
|
||||
|
||||
create view user_mention_mview as
|
||||
with all_comment as
|
||||
(
|
||||
select
|
||||
ca.*
|
||||
from comment_aggregates_mview ca
|
||||
)
|
||||
|
||||
select
|
||||
ac.id,
|
||||
um.id as user_mention_id,
|
||||
ac.creator_id,
|
||||
ac.post_id,
|
||||
ac.parent_id,
|
||||
ac.content,
|
||||
ac.removed,
|
||||
um.read,
|
||||
ac.published,
|
||||
ac.updated,
|
||||
ac.deleted,
|
||||
ac.community_id,
|
||||
ac.community_name,
|
||||
ac.banned,
|
||||
ac.banned_from_community,
|
||||
ac.creator_name,
|
||||
ac.creator_avatar,
|
||||
ac.score,
|
||||
ac.upvotes,
|
||||
ac.downvotes,
|
||||
ac.hot_rank,
|
||||
u.id as user_id,
|
||||
coalesce(cl.score, 0) as my_vote,
|
||||
(select cs.id::bool from comment_saved cs where u.id = cs.user_id and cs.comment_id = ac.id) as saved,
|
||||
um.recipient_id
|
||||
from user_ u
|
||||
cross join all_comment ac
|
||||
left join comment_like cl on u.id = cl.user_id and ac.id = cl.comment_id
|
||||
left join user_mention um on um.comment_id = ac.id
|
||||
|
||||
union all
|
||||
|
||||
select
|
||||
ac.id,
|
||||
um.id as user_mention_id,
|
||||
ac.creator_id,
|
||||
ac.post_id,
|
||||
ac.parent_id,
|
||||
ac.content,
|
||||
ac.removed,
|
||||
um.read,
|
||||
ac.published,
|
||||
ac.updated,
|
||||
ac.deleted,
|
||||
ac.community_id,
|
||||
ac.community_name,
|
||||
ac.banned,
|
||||
ac.banned_from_community,
|
||||
ac.creator_name,
|
||||
ac.creator_avatar,
|
||||
ac.score,
|
||||
ac.upvotes,
|
||||
ac.downvotes,
|
||||
ac.hot_rank,
|
||||
null as user_id,
|
||||
null as my_vote,
|
||||
null as saved,
|
||||
um.recipient_id
|
||||
from all_comment ac
|
||||
left join user_mention um on um.comment_id = ac.id
|
||||
;
|
||||
|
@ -0,0 +1,88 @@
|
||||
drop view post_view;
|
||||
drop view post_mview;
|
||||
drop materialized view post_aggregates_mview;
|
||||
drop view post_aggregates_view;
|
||||
|
||||
-- regen post view
|
||||
create view post_aggregates_view as
|
||||
select
|
||||
p.*,
|
||||
(select u.banned from user_ u where p.creator_id = u.id) as banned,
|
||||
(select cb.id::bool from community_user_ban cb where p.creator_id = cb.user_id and p.community_id = cb.community_id) as banned_from_community,
|
||||
(select name from user_ where p.creator_id = user_.id) as creator_name,
|
||||
(select avatar from user_ where p.creator_id = user_.id) as creator_avatar,
|
||||
(select name from community where p.community_id = community.id) as community_name,
|
||||
(select removed from community c where p.community_id = c.id) as community_removed,
|
||||
(select deleted from community c where p.community_id = c.id) as community_deleted,
|
||||
(select nsfw from community c where p.community_id = c.id) as community_nsfw,
|
||||
(select count(*) from comment where comment.post_id = p.id) as number_of_comments,
|
||||
coalesce(sum(pl.score), 0) as score,
|
||||
count (case when pl.score = 1 then 1 else null end) as upvotes,
|
||||
count (case when pl.score = -1 then 1 else null end) as downvotes,
|
||||
hot_rank(coalesce(sum(pl.score) , 0), p.published) as hot_rank
|
||||
from post p
|
||||
left join post_like pl on p.id = pl.post_id
|
||||
group by p.id;
|
||||
|
||||
create materialized view post_aggregates_mview as select * from post_aggregates_view;
|
||||
|
||||
create unique index idx_post_aggregates_mview_id on post_aggregates_mview (id);
|
||||
|
||||
create view post_view as
|
||||
with all_post as (
|
||||
select
|
||||
pa.*
|
||||
from post_aggregates_view pa
|
||||
)
|
||||
select
|
||||
ap.*,
|
||||
u.id as user_id,
|
||||
coalesce(pl.score, 0) as my_vote,
|
||||
(select cf.id::bool from community_follower cf where u.id = cf.user_id and cf.community_id = ap.community_id) as subscribed,
|
||||
(select pr.id::bool from post_read pr where u.id = pr.user_id and pr.post_id = ap.id) as read,
|
||||
(select ps.id::bool from post_saved ps where u.id = ps.user_id and ps.post_id = ap.id) as saved
|
||||
from user_ u
|
||||
cross join all_post ap
|
||||
left join post_like pl on u.id = pl.user_id and ap.id = pl.post_id
|
||||
|
||||
union all
|
||||
|
||||
select
|
||||
ap.*,
|
||||
null as user_id,
|
||||
null as my_vote,
|
||||
null as subscribed,
|
||||
null as read,
|
||||
null as saved
|
||||
from all_post ap
|
||||
;
|
||||
|
||||
create view post_mview as
|
||||
with all_post as (
|
||||
select
|
||||
pa.*
|
||||
from post_aggregates_mview pa
|
||||
)
|
||||
select
|
||||
ap.*,
|
||||
u.id as user_id,
|
||||
coalesce(pl.score, 0) as my_vote,
|
||||
(select cf.id::bool from community_follower cf where u.id = cf.user_id and cf.community_id = ap.community_id) as subscribed,
|
||||
(select pr.id::bool from post_read pr where u.id = pr.user_id and pr.post_id = ap.id) as read,
|
||||
(select ps.id::bool from post_saved ps where u.id = ps.user_id and ps.post_id = ap.id) as saved
|
||||
from user_ u
|
||||
cross join all_post ap
|
||||
left join post_like pl on u.id = pl.user_id and ap.id = pl.post_id
|
||||
|
||||
union all
|
||||
|
||||
select
|
||||
ap.*,
|
||||
null as user_id,
|
||||
null as my_vote,
|
||||
null as subscribed,
|
||||
null as read,
|
||||
null as saved
|
||||
from all_post ap
|
||||
;
|
||||
|
@ -0,0 +1,106 @@
|
||||
-- Adds a newest_activity_time for the post_views, in order to sort by newest comment
|
||||
drop view post_view;
|
||||
drop view post_mview;
|
||||
drop materialized view post_aggregates_mview;
|
||||
drop view post_aggregates_view;
|
||||
|
||||
-- regen post view
|
||||
create view post_aggregates_view as
|
||||
select
|
||||
p.*,
|
||||
(select u.banned from user_ u where p.creator_id = u.id) as banned,
|
||||
(select cb.id::bool from community_user_ban cb where p.creator_id = cb.user_id and p.community_id = cb.community_id) as banned_from_community,
|
||||
(select name from user_ where p.creator_id = user_.id) as creator_name,
|
||||
(select avatar from user_ where p.creator_id = user_.id) as creator_avatar,
|
||||
(select name from community where p.community_id = community.id) as community_name,
|
||||
(select removed from community c where p.community_id = c.id) as community_removed,
|
||||
(select deleted from community c where p.community_id = c.id) as community_deleted,
|
||||
(select nsfw from community c where p.community_id = c.id) as community_nsfw,
|
||||
(select count(*) from comment where comment.post_id = p.id) as number_of_comments,
|
||||
coalesce(sum(pl.score), 0) as score,
|
||||
count (case when pl.score = 1 then 1 else null end) as upvotes,
|
||||
count (case when pl.score = -1 then 1 else null end) as downvotes,
|
||||
hot_rank(coalesce(sum(pl.score) , 0),
|
||||
(
|
||||
case when (p.published < ('now'::timestamp - '1 month'::interval)) then p.published -- Prevents necro-bumps
|
||||
else greatest(c.recent_comment_time, p.published)
|
||||
end
|
||||
)
|
||||
) as hot_rank,
|
||||
(
|
||||
case when (p.published < ('now'::timestamp - '1 month'::interval)) then p.published -- Prevents necro-bumps
|
||||
else greatest(c.recent_comment_time, p.published)
|
||||
end
|
||||
) as newest_activity_time
|
||||
from post p
|
||||
left join post_like pl on p.id = pl.post_id
|
||||
left join (
|
||||
select post_id,
|
||||
max(published) as recent_comment_time
|
||||
from comment
|
||||
group by 1
|
||||
) c on p.id = c.post_id
|
||||
group by p.id, c.recent_comment_time;
|
||||
|
||||
create materialized view post_aggregates_mview as select * from post_aggregates_view;
|
||||
|
||||
create unique index idx_post_aggregates_mview_id on post_aggregates_mview (id);
|
||||
|
||||
create view post_view as
|
||||
with all_post as (
|
||||
select
|
||||
pa.*
|
||||
from post_aggregates_view pa
|
||||
)
|
||||
select
|
||||
ap.*,
|
||||
u.id as user_id,
|
||||
coalesce(pl.score, 0) as my_vote,
|
||||
(select cf.id::bool from community_follower cf where u.id = cf.user_id and cf.community_id = ap.community_id) as subscribed,
|
||||
(select pr.id::bool from post_read pr where u.id = pr.user_id and pr.post_id = ap.id) as read,
|
||||
(select ps.id::bool from post_saved ps where u.id = ps.user_id and ps.post_id = ap.id) as saved
|
||||
from user_ u
|
||||
cross join all_post ap
|
||||
left join post_like pl on u.id = pl.user_id and ap.id = pl.post_id
|
||||
|
||||
union all
|
||||
|
||||
select
|
||||
ap.*,
|
||||
null as user_id,
|
||||
null as my_vote,
|
||||
null as subscribed,
|
||||
null as read,
|
||||
null as saved
|
||||
from all_post ap
|
||||
;
|
||||
|
||||
create view post_mview as
|
||||
with all_post as (
|
||||
select
|
||||
pa.*
|
||||
from post_aggregates_mview pa
|
||||
)
|
||||
select
|
||||
ap.*,
|
||||
u.id as user_id,
|
||||
coalesce(pl.score, 0) as my_vote,
|
||||
(select cf.id::bool from community_follower cf where u.id = cf.user_id and cf.community_id = ap.community_id) as subscribed,
|
||||
(select pr.id::bool from post_read pr where u.id = pr.user_id and pr.post_id = ap.id) as read,
|
||||
(select ps.id::bool from post_saved ps where u.id = ps.user_id and ps.post_id = ap.id) as saved
|
||||
from user_ u
|
||||
cross join all_post ap
|
||||
left join post_like pl on u.id = pl.user_id and ap.id = pl.post_id
|
||||
|
||||
union all
|
||||
|
||||
select
|
||||
ap.*,
|
||||
null as user_id,
|
||||
null as my_vote,
|
||||
null as subscribed,
|
||||
null as read,
|
||||
null as saved
|
||||
from all_post ap
|
||||
;
|
||||
|
@ -1 +1 @@
|
||||
pub const VERSION: &str = "v0.6.11";
|
||||
pub const VERSION: &str = "v0.6.25";
|
||||
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,65 @@
|
||||
import { Component, linkEvent } from 'inferno';
|
||||
import { DataType } from '../interfaces';
|
||||
|
||||
import { i18n } from '../i18next';
|
||||
|
||||
interface DataTypeSelectProps {
|
||||
type_: DataType;
|
||||
onChange?(val: DataType): any;
|
||||
}
|
||||
|
||||
interface DataTypeSelectState {
|
||||
type_: DataType;
|
||||
}
|
||||
|
||||
export class DataTypeSelect extends Component<
|
||||
DataTypeSelectProps,
|
||||
DataTypeSelectState
|
||||
> {
|
||||
private emptyState: DataTypeSelectState = {
|
||||
type_: this.props.type_,
|
||||
};
|
||||
|
||||
constructor(props: any, context: any) {
|
||||
super(props, context);
|
||||
this.state = this.emptyState;
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div class="btn-group btn-group-toggle">
|
||||
<label
|
||||
className={`pointer btn btn-sm btn-secondary
|
||||
${this.state.type_ == DataType.Post && 'active'}
|
||||
`}
|
||||
>
|
||||
<input
|
||||
type="radio"
|
||||
value={DataType.Post}
|
||||
checked={this.state.type_ == DataType.Post}
|
||||
onChange={linkEvent(this, this.handleTypeChange)}
|
||||
/>
|
||||
{i18n.t('posts')}
|
||||
</label>
|
||||
<label
|
||||
className={`pointer btn btn-sm btn-secondary ${this.state.type_ ==
|
||||
DataType.Comment && 'active'}`}
|
||||
>
|
||||
<input
|
||||
type="radio"
|
||||
value={DataType.Comment}
|
||||
checked={this.state.type_ == DataType.Comment}
|
||||
onChange={linkEvent(this, this.handleTypeChange)}
|
||||
/>
|
||||
{i18n.t('comments')}
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
handleTypeChange(i: DataTypeSelect, event: any) {
|
||||
i.state.type_ = Number(event.target.value);
|
||||
i.setState(i.state);
|
||||
i.props.onChange(i.state.type_);
|
||||
}
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
import { Component, linkEvent } from 'inferno';
|
||||
import { FramelyData } from '../interfaces';
|
||||
import { mdToHtml } from '../utils';
|
||||
|
||||
interface FramelyCardProps {
|
||||
iframely: FramelyData;
|
||||
}
|
||||
|
||||
interface FramelyCardState {
|
||||
expanded: boolean;
|
||||
}
|
||||
|
||||
export class IFramelyCard extends Component<
|
||||
FramelyCardProps,
|
||||
FramelyCardState
|
||||
> {
|
||||
private emptyState: FramelyCardState = {
|
||||
expanded: false,
|
||||
};
|
||||
|
||||
constructor(props: any, context: any) {
|
||||
super(props, context);
|
||||
this.state = this.emptyState;
|
||||
}
|
||||
|
||||
render() {
|
||||
let iframely = this.props.iframely;
|
||||
return (
|
||||
<>
|
||||
{iframely.title && !this.state.expanded && (
|
||||
<div class="card mt-3 mb-2">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title d-inline">
|
||||
<span>
|
||||
<a class="text-body" target="_blank" href={iframely.url}>
|
||||
{iframely.title}
|
||||
</a>
|
||||
</span>
|
||||
</h5>
|
||||
<span class="d-inline-block ml-2 mb-2 small text-muted">
|
||||
<a
|
||||
class="text-muted font-italic"
|
||||
target="_blank"
|
||||
href={iframely.url}
|
||||
>
|
||||
{new URL(iframely.url).hostname}
|
||||
<svg class="ml-1 icon">
|
||||
<use xlinkHref="#icon-external-link"></use>
|
||||
</svg>
|
||||
</a>
|
||||
{iframely.html && (
|
||||
<span
|
||||
class="ml-2 pointer text-monospace"
|
||||
onClick={linkEvent(this, this.handleIframeExpand)}
|
||||
>
|
||||
{this.state.expanded ? '[-]' : '[+]'}
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
{iframely.description && (
|
||||
<div
|
||||
className="card-text small text-muted md-div"
|
||||
dangerouslySetInnerHTML={mdToHtml(iframely.description)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{this.state.expanded && (
|
||||
<div
|
||||
class="mt-3 mb-2"
|
||||
dangerouslySetInnerHTML={{ __html: iframely.html }}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
handleIframeExpand(i: IFramelyCard) {
|
||||
i.state.expanded = !i.state.expanded;
|
||||
i.setState(i.state);
|
||||
}
|
||||
}
|
@ -0,0 +1,241 @@
|
||||
export const pt_BR = {
|
||||
translation: {
|
||||
post: 'publicação',
|
||||
remove_post: 'Apagar publicação',
|
||||
no_posts: 'Sem publicações.',
|
||||
create_a_post: 'Criar uma publicação',
|
||||
create_post: 'Criar publicação',
|
||||
number_of_posts: '{{count}} publicações',
|
||||
posts: 'Publicações',
|
||||
related_posts: 'Essas publicações podem estar relacionadas',
|
||||
cross_posts: 'Esse link também foi publicado em:',
|
||||
cross_post: 're-publicar',
|
||||
cross_posted_to: 'Publicado também em: ',
|
||||
comments: 'Comentários',
|
||||
number_of_comments: '{{count}} comentários',
|
||||
remove_comment: 'Apagar comentário',
|
||||
communities: 'Comunidades',
|
||||
users: 'Usuários',
|
||||
create_a_community: 'Criar uma comunidade',
|
||||
create_community: 'Criar comunidade',
|
||||
remove_community: 'Apagar comunidade',
|
||||
subscribed_to_communities: 'Inscrito em <1>comunidades</1>',
|
||||
trending_communities: '<1>Comunidades</1> em tendência',
|
||||
list_of_communities: 'Lista de comunidades',
|
||||
number_of_communities: '{{count}} comunidades',
|
||||
community_reqs: 'minúsculas, sublinhados e sem espaços.',
|
||||
create_private_message: 'Criar mensagem privada',
|
||||
send_secure_message: 'Enviar mensagem segura',
|
||||
send_message: 'Enviar mensagem',
|
||||
message: 'Mensagem',
|
||||
edit: 'editar',
|
||||
reply: 'responder',
|
||||
cancel: 'Cancelar',
|
||||
preview: 'Pré-visualização',
|
||||
upload_image: 'fazer upload de imagem',
|
||||
avatar: 'Avatar',
|
||||
upload_avatar: 'Fazer upload de avatar',
|
||||
show_avatars: 'Mostrar Avatars',
|
||||
formatting_help: 'ajuda de formatação',
|
||||
view_source: 'ver fonte',
|
||||
unlock: 'desbloquear',
|
||||
lock: 'bloquear',
|
||||
sticky: 'fixar',
|
||||
unsticky: 'desafixar',
|
||||
link: 'link',
|
||||
archive_link: 'arquivar link',
|
||||
mod: 'moderador',
|
||||
mods: 'moderadores',
|
||||
moderates: 'Modera',
|
||||
settings: 'Configurações',
|
||||
remove_as_mod: 'remover como moderador',
|
||||
appoint_as_mod: 'designar como moderador',
|
||||
modlog: 'Registro de moderação',
|
||||
admin: 'administrador',
|
||||
admins: 'administradores',
|
||||
remove_as_admin: 'remover como administrador',
|
||||
appoint_as_admin: 'designar como administrador',
|
||||
remove: 'remover',
|
||||
removed: 'removido',
|
||||
locked: 'trancado',
|
||||
stickied: 'fixado',
|
||||
reason: 'Motivo',
|
||||
mark_as_read: 'marcar como lido',
|
||||
mark_as_unread: 'marcar como não lido',
|
||||
delete: 'apagar',
|
||||
deleted: 'apagado',
|
||||
delete_account: 'Apagar conta',
|
||||
delete_account_confirm:
|
||||
'Aviso: isso vai apagar seus dados de forma permanente. Escreva sua senha para confirmar.',
|
||||
restore: 'restaurar',
|
||||
ban: 'banir',
|
||||
ban_from_site: 'banido do site',
|
||||
unban: 'readmitido',
|
||||
unban_from_site: 'readmitido ao site',
|
||||
banned: 'banido',
|
||||
save: 'guardar',
|
||||
unsave: 'descartar',
|
||||
create: 'criar',
|
||||
creator: 'criador',
|
||||
username: 'nome de usuário',
|
||||
email_or_username: 'E-mail ou nome de usuário',
|
||||
number_of_users: '{{count}} usuários',
|
||||
number_of_subscribers: '{{count}} inscritos',
|
||||
number_of_points: '{{count}} pontos',
|
||||
number_online: '{{count}} usuários online',
|
||||
name: 'Nome',
|
||||
title: 'Título',
|
||||
category: 'Categoria',
|
||||
subscribers: 'Inscritos',
|
||||
both: 'Ambos',
|
||||
saved: 'Guardado',
|
||||
unsubscribe: 'Cancelar inscrição',
|
||||
subscribe: 'Inscrever-se',
|
||||
subscribed: 'Inscrito',
|
||||
prev: 'Anterior',
|
||||
next: 'Próximo',
|
||||
sidebar: 'Barra lateral',
|
||||
sort_type: 'Ordenação',
|
||||
hot: 'Popular',
|
||||
new: 'Novo',
|
||||
old: 'Velho',
|
||||
top_day: 'Top do dia',
|
||||
week: 'Semana',
|
||||
month: 'Mês',
|
||||
year: 'Ano',
|
||||
all: 'Tudo',
|
||||
top: 'Top',
|
||||
api: 'API',
|
||||
docs: 'Docs',
|
||||
inbox: 'Caixa de entrada',
|
||||
inbox_for: 'Caixa de entrada de <1>{{user}}</1>',
|
||||
mark_all_as_read: 'marcar tudo como lido',
|
||||
type: 'Tipo',
|
||||
unread: 'Não lido',
|
||||
replies: 'Respostas',
|
||||
mentions: 'Menções',
|
||||
reply_sent: 'Resposta enviada',
|
||||
message_sent: 'Mensagem enviada',
|
||||
search: 'Busca',
|
||||
overview: 'Visão geral',
|
||||
view: 'Visualização',
|
||||
logout: 'Sair',
|
||||
login_sign_up: 'Entrar / Inscrever-se',
|
||||
login: 'Entrar',
|
||||
sign_up: 'Inscrever-se',
|
||||
notifications_error:
|
||||
'Seu navegador não oferece notificações para a área de trabalho. Tente o Firefox ou o Chrome.',
|
||||
unread_messages: 'Mensagens não lidas',
|
||||
messages: 'Mensagens',
|
||||
password: 'Senha',
|
||||
verify_password: 'Verifique a senha',
|
||||
old_password: 'Senha antiga',
|
||||
forgot_password: 'esqueci a senha',
|
||||
reset_password_mail_sent: 'Enviado um e-mail para a alteração da senha.',
|
||||
password_change: 'Alteração de senha',
|
||||
new_password: 'Nova senha',
|
||||
no_email_setup: 'Esse servidor não configurou corretamente o e-mail.',
|
||||
email: 'E-mail',
|
||||
matrix_user_id: 'Usuário Matrix',
|
||||
private_message_disclaimer:
|
||||
'Aviso: mensagens privadas no Lemmy não são seguras. Crie uma conta em <1>Riot.im</1> para troca segura de mensagens.',
|
||||
send_notifications_to_email: 'Enviar notificações para o e-mail',
|
||||
optional: 'Opcional',
|
||||
expires: 'Expira',
|
||||
language: 'Idioma',
|
||||
browser_default: 'Padrão do navegador',
|
||||
downvotes_disabled: 'Votos negativos desativados',
|
||||
enable_downvotes: 'Permitir votos negativos',
|
||||
open_registration: 'Permitir registro',
|
||||
registration_closed: 'Registros desativados',
|
||||
enable_nsfw: 'Permitir NSFW',
|
||||
url: 'URL',
|
||||
body: 'Conteúdo',
|
||||
copy_suggested_title: 'copiar título sugerido: {{title}}',
|
||||
community: 'Comunidade',
|
||||
expand_here: 'Expandir aqui',
|
||||
subscribe_to_communities: 'Inscreva-se em algumas <1>comunidades</1>.',
|
||||
chat: 'Chat',
|
||||
recent_comments: 'Últimos comentários',
|
||||
no_results: 'Nenhum resultado.',
|
||||
setup: 'Instalação',
|
||||
lemmy_instance_setup: 'Criação de instância Lemmy',
|
||||
setup_admin: 'Configurar administrador do site',
|
||||
your_site: 'seu site',
|
||||
modified: 'modificado',
|
||||
nsfw: 'NSFW',
|
||||
show_nsfw: 'Mostrar conteúdo NSFW',
|
||||
theme: 'Tema',
|
||||
sponsors: 'Patrocinadores',
|
||||
sponsors_of_lemmy: 'Patrocinadores do Lemmy',
|
||||
sponsor_message:
|
||||
'Lemmy é um programa livre e de código aberto, o que significa que não haverá publicidade, monetização ou capital de risco, jamais. Suas doações apoiam de forma direta o desenvolvimento em tempo integral do projeto. Muitos agradecimentos às sequintes pessoas:',
|
||||
support_on_patreon: 'Colabore no Patreon',
|
||||
support_on_liberapay: 'Colabore no Liberapay',
|
||||
donate_to_lemmy: 'Faça uma doação ao Lemmy',
|
||||
donate: 'Doar',
|
||||
general_sponsors:
|
||||
'Patrocinadores são aqueles que doaram entre $10 e $39 ao Lemmy.',
|
||||
crypto: 'Crypto',
|
||||
bitcoin: 'Bitcoin',
|
||||
ethereum: 'Ethereum',
|
||||
monero: 'Monero',
|
||||
code: 'Code',
|
||||
joined: 'Entrou',
|
||||
by: 'por',
|
||||
to: 'para',
|
||||
from: 'de',
|
||||
transfer_community: 'transferir comunidade',
|
||||
transfer_site: 'transferir site',
|
||||
are_you_sure: 'tem certeza?',
|
||||
yes: 'sim',
|
||||
no: 'não',
|
||||
powered_by: 'Powered by',
|
||||
landing_0:
|
||||
'Lemmy é um <1>agregador de links</1> / alternativa ao reddit, com a intenção de funcionar junto ao <2>fediverso</2>.<3></3>Pode ser hospedado em servidor próprio, tem atualização de comentários em tempo real e é minúsculo (<4>~80kB</4>). A federação com a rede ActivityPub está no roteiro do projeto. <5></5>Esta é uma <6>versão beta bastante antecipada</6>, e muitas funcionalidades ainda estão quebradas ou ausentes. <7></7>Sugira novas funcionalidades ou reporte erros <8>aqui.</8><9></9>Feito com <10>Rust</10>, <11>Actix</11>, <12>Inferno</12>, <13>Typescript</13>.',
|
||||
not_logged_in: 'Não autenticado.',
|
||||
logged_in: 'Autenticado.',
|
||||
community_ban: 'Você foi banido desta comunidade.',
|
||||
site_ban: 'Você foi banido do site',
|
||||
couldnt_create_comment: 'Não foi possível criar o comentário.',
|
||||
couldnt_like_comment: 'Não foi possível curtir o comentário.',
|
||||
couldnt_update_comment: 'Não foi possível atualizar o comentário.',
|
||||
couldnt_save_comment: 'Não foi possível guardar o comentário.',
|
||||
no_comment_edit_allowed: 'Sem permissão para editar de comentário.',
|
||||
no_post_edit_allowed: 'Sem permissão para editar publicação.',
|
||||
no_community_edit_allowed: 'Sem permissão para editar comunidade.',
|
||||
couldnt_find_community: 'Não foi possível encontrar a comunidade.',
|
||||
couldnt_update_community: 'Não foi possível atualizar a comunidade.',
|
||||
community_already_exists: 'Esta comunidade já existe.',
|
||||
community_moderator_already_exists:
|
||||
'Este moderador da comunidade já existe.',
|
||||
community_follower_already_exists: 'Este seguidor da comunidade já existe.',
|
||||
community_user_already_banned: 'Este usuário da comunidade já foi banido.',
|
||||
couldnt_create_post: 'Não foi possível criar a publicação.',
|
||||
couldnt_like_post: 'Não foi possível curtir a publicação.',
|
||||
couldnt_find_post: 'Não foi possível encontrar a publicação.',
|
||||
couldnt_get_posts: 'Não foi possível obter as publicações',
|
||||
couldnt_update_post: 'Não foi possível atualizar a publicação',
|
||||
couldnt_save_post: 'Não foi possível guardar a publicação.',
|
||||
no_slurs: 'Sem insultos.',
|
||||
not_an_admin: 'Não é administrador.',
|
||||
site_already_exists: 'O site já existe.',
|
||||
couldnt_update_site: 'Não foi possível atualizar o site.',
|
||||
couldnt_find_that_username_or_email:
|
||||
'Não foi possível encontrar esse usuário ou e-mail.',
|
||||
password_incorrect: 'Senha incorreta.',
|
||||
passwords_dont_match: 'As senhas não são iguais.',
|
||||
admin_already_created: 'Desculpe, já há um administrador.',
|
||||
user_already_exists: 'Este usuário já existe.',
|
||||
email_already_exists: 'Este e-mail já existe.',
|
||||
couldnt_update_user: 'Não foi possível atualizar o usuário.',
|
||||
system_err_login: 'Erro no sistema. Tente sair e autenticar-se outra vez.',
|
||||
couldnt_create_private_message: 'Não foi possível criar mensagem privada.',
|
||||
no_private_message_edit_allowed:
|
||||
'Sem permissão para editar mensagem privada.',
|
||||
couldnt_update_private_message:
|
||||
'Não foi possível atualizar a mensagem privada.',
|
||||
time: 'Tempo',
|
||||
action: 'Ação',
|
||||
},
|
||||
};
|
@ -1 +1 @@
|
||||
export const version: string = 'v0.6.11';
|
||||
export const version: string = 'v0.6.25';
|
||||
|
Loading…
Reference in New Issue