18 Commits

Author SHA1 Message Date
dec8a0660e css fix 2025-02-26 13:45:28 +01:00
283e25178b fix ecto bug related to pg_bouncer 2024-12-19 15:07:55 +01:00
4cde4c8f67 fix filtering ignored posts 2024-08-20 14:02:40 +02:00
d497eaa522 debug check_origin on render 2024-08-14 11:13:08 +02:00
eb47a26de7 removed dbg 2024-08-14 11:11:12 +02:00
256c883488 nicer pagination 2024-08-12 16:52:26 +02:00
6d64449c1b fix last page calculation 2024-08-12 16:52:01 +02:00
6751ade1d9 fix empty new_posts count 2024-08-12 16:37:50 +02:00
bf7f1a4601 update deps 2024-08-12 16:27:36 +02:00
bab66c8079 fix attachment links 2024-08-12 16:19:22 +02:00
914246f08a add credo 2024-08-12 16:19:06 +02:00
0c52c18d92 Merge branch 'develop' 2024-08-12 15:52:28 +02:00
cb66d127b6 remove plausible 2024-08-12 15:52:14 +02:00
ce5a011d90 Merge branch 'feature/meeseeks-parser' into develop 2024-08-12 15:50:41 +02:00
8383d00335 Merge branch 'feature/meeseeks-parser' into develop 2024-08-12 11:51:18 +02:00
4cc2ee8276 add plausible tracking 2024-06-11 01:22:46 +02:00
36d97eebec Merge branch 'feature/meeseeks-parser' into develop 2024-06-04 00:08:38 +02:00
c29ae7f3e4 make sure bbpassword is still in session otherwise relogin 2024-06-03 20:39:12 +02:00
10 changed files with 268 additions and 15 deletions

217
.credo.exs Normal file
View File

@ -0,0 +1,217 @@
# This file contains the configuration for Credo and you are probably reading
# this after creating it with `mix credo.gen.config`.
#
# If you find anything wrong or unclear in this file, please report an
# issue on GitHub: https://github.com/rrrene/credo/issues
#
%{
#
# You can have as many configs as you like in the `configs:` field.
configs: [
%{
#
# Run any config using `mix credo -C <name>`. If no config name is given
# "default" is used.
#
name: "default",
#
# These are the files included in the analysis:
files: %{
#
# You can give explicit globs or simply directories.
# In the latter case `**/*.{ex,exs}` will be used.
#
included: [
"lib/",
"src/",
"test/",
"web/",
"apps/*/lib/",
"apps/*/src/",
"apps/*/test/",
"apps/*/web/"
],
excluded: [~r"/_build/", ~r"/deps/", ~r"/node_modules/"]
},
#
# Load and configure plugins here:
#
plugins: [],
#
# If you create your own checks, you must specify the source files for
# them here, so they can be loaded by Credo before running the analysis.
#
requires: [],
#
# If you want to enforce a style guide and need a more traditional linting
# experience, you can change `strict` to `true` below:
#
strict: true,
#
# To modify the timeout for parsing files, change this value:
#
parse_timeout: 5000,
#
# If you want to use uncolored output by default, you can change `color`
# to `false` below:
#
color: true,
#
# You can customize the parameters of any check by adding a second element
# to the tuple.
#
# To disable a check put `false` as second element:
#
# {Credo.Check.Design.DuplicatedCode, false}
#
checks: %{
enabled: [
#
## Consistency Checks
#
{Credo.Check.Consistency.ExceptionNames, []},
{Credo.Check.Consistency.LineEndings, []},
{Credo.Check.Consistency.ParameterPatternMatching, []},
{Credo.Check.Consistency.SpaceAroundOperators, []},
{Credo.Check.Consistency.SpaceInParentheses, []},
{Credo.Check.Consistency.TabsOrSpaces, []},
#
## Design Checks
#
# You can customize the priority of any check
# Priority values are: `low, normal, high, higher`
#
{Credo.Check.Design.AliasUsage,
[priority: :low, if_nested_deeper_than: 2, if_called_more_often_than: 0]},
{Credo.Check.Design.TagFIXME, []},
# You can also customize the exit_status of each check.
# If you don't want TODO comments to cause `mix credo` to fail, just
# set this value to 0 (zero).
#
{Credo.Check.Design.TagTODO, [exit_status: 2]},
#
## Readability Checks
#
{Credo.Check.Readability.AliasOrder, []},
{Credo.Check.Readability.FunctionNames, []},
{Credo.Check.Readability.LargeNumbers, []},
{Credo.Check.Readability.MaxLineLength, [priority: :low, max_length: 120]},
{Credo.Check.Readability.ModuleAttributeNames, []},
{Credo.Check.Readability.ModuleDoc, []},
{Credo.Check.Readability.ModuleNames, []},
{Credo.Check.Readability.ParenthesesInCondition, []},
{Credo.Check.Readability.ParenthesesOnZeroArityDefs, []},
{Credo.Check.Readability.PipeIntoAnonymousFunctions, []},
{Credo.Check.Readability.PredicateFunctionNames, []},
{Credo.Check.Readability.PreferImplicitTry, []},
{Credo.Check.Readability.RedundantBlankLines, []},
{Credo.Check.Readability.Semicolons, []},
{Credo.Check.Readability.SpaceAfterCommas, []},
{Credo.Check.Readability.StringSigils, []},
{Credo.Check.Readability.TrailingBlankLine, []},
{Credo.Check.Readability.TrailingWhiteSpace, []},
{Credo.Check.Readability.UnnecessaryAliasExpansion, []},
{Credo.Check.Readability.VariableNames, []},
{Credo.Check.Readability.WithSingleClause, []},
#
## Refactoring Opportunities
#
{Credo.Check.Refactor.Apply, []},
{Credo.Check.Refactor.CondStatements, []},
{Credo.Check.Refactor.CyclomaticComplexity, []},
{Credo.Check.Refactor.FilterCount, []},
{Credo.Check.Refactor.FilterFilter, []},
{Credo.Check.Refactor.FunctionArity, []},
{Credo.Check.Refactor.LongQuoteBlocks, []},
{Credo.Check.Refactor.MapJoin, []},
{Credo.Check.Refactor.MatchInCondition, []},
{Credo.Check.Refactor.NegatedConditionsInUnless, []},
{Credo.Check.Refactor.NegatedConditionsWithElse, []},
{Credo.Check.Refactor.Nesting, []},
{Credo.Check.Refactor.RedundantWithClauseResult, []},
{Credo.Check.Refactor.RejectReject, []},
{Credo.Check.Refactor.UnlessWithElse, []},
{Credo.Check.Refactor.WithClauses, []},
#
## Warnings
#
{Credo.Check.Warning.ApplicationConfigInModuleAttribute, []},
{Credo.Check.Warning.BoolOperationOnSameValues, []},
{Credo.Check.Warning.Dbg, []},
{Credo.Check.Warning.ExpensiveEmptyEnumCheck, []},
{Credo.Check.Warning.IExPry, []},
{Credo.Check.Warning.IoInspect, []},
{Credo.Check.Warning.MissedMetadataKeyInLoggerConfig, []},
{Credo.Check.Warning.OperationOnSameValues, []},
{Credo.Check.Warning.OperationWithConstantResult, []},
{Credo.Check.Warning.RaiseInsideRescue, []},
{Credo.Check.Warning.SpecWithStruct, []},
{Credo.Check.Warning.UnsafeExec, []},
{Credo.Check.Warning.UnusedEnumOperation, []},
{Credo.Check.Warning.UnusedFileOperation, []},
{Credo.Check.Warning.UnusedKeywordOperation, []},
{Credo.Check.Warning.UnusedListOperation, []},
{Credo.Check.Warning.UnusedPathOperation, []},
{Credo.Check.Warning.UnusedRegexOperation, []},
{Credo.Check.Warning.UnusedStringOperation, []},
{Credo.Check.Warning.UnusedTupleOperation, []},
{Credo.Check.Warning.WrongTestFileExtension, []}
],
disabled: [
#
# Checks scheduled for next check update (opt-in for now)
{Credo.Check.Refactor.UtcNowTruncate, []},
#
# Controversial and experimental checks (opt-in, just move the check to `:enabled`
# and be sure to use `mix credo --strict` to see low priority checks)
#
{Credo.Check.Consistency.MultiAliasImportRequireUse, []},
{Credo.Check.Consistency.UnusedVariableNames, []},
{Credo.Check.Design.DuplicatedCode, []},
{Credo.Check.Design.SkipTestWithoutComment, []},
{Credo.Check.Readability.AliasAs, []},
{Credo.Check.Readability.BlockPipe, []},
{Credo.Check.Readability.ImplTrue, []},
{Credo.Check.Readability.MultiAlias, []},
{Credo.Check.Readability.NestedFunctionCalls, []},
{Credo.Check.Readability.OneArityFunctionInPipe, []},
{Credo.Check.Readability.OnePipePerLine, []},
{Credo.Check.Readability.SeparateAliasRequire, []},
{Credo.Check.Readability.SingleFunctionToBlockPipe, []},
{Credo.Check.Readability.SinglePipe, []},
{Credo.Check.Readability.Specs, []},
{Credo.Check.Readability.StrictModuleLayout, []},
{Credo.Check.Readability.WithCustomTaggedTuple, []},
{Credo.Check.Refactor.ABCSize, []},
{Credo.Check.Refactor.AppendSingleItem, []},
{Credo.Check.Refactor.DoubleBooleanNegation, []},
{Credo.Check.Refactor.FilterReject, []},
{Credo.Check.Refactor.IoPuts, []},
{Credo.Check.Refactor.MapMap, []},
{Credo.Check.Refactor.ModuleDependencies, []},
{Credo.Check.Refactor.NegatedIsNil, []},
{Credo.Check.Refactor.PassAsyncInTestCases, []},
{Credo.Check.Refactor.PipeChainStart, []},
{Credo.Check.Refactor.RejectFilter, []},
{Credo.Check.Refactor.VariableRebinding, []},
{Credo.Check.Warning.LazyLogging, []},
{Credo.Check.Warning.LeakyEnvironment, []},
{Credo.Check.Warning.MapGetUnsafePass, []},
{Credo.Check.Warning.MixEnv, []},
{Credo.Check.Warning.UnsafeToAtom, []}
# {Credo.Check.Refactor.MapInto, []},
#
# Custom checks can be created using `mix credo.gen.check`.
#
]
}
}
]
}

View File

@ -5,7 +5,7 @@
/* This file is for your main application CSS */
body {
@apply bg-base-300 text-[14pt] leading-8 overflow-x-hidden;
@apply bg-base-300 font-['Inter'] text-[18px] leading-6 overflow-x-hidden;
}
.post {
@ -36,11 +36,14 @@ body {
.post .code pre:before { @apply mr-0; }
.post .code h5 { @apply hidden; }
.post a[href] { @apply link; }
.post .bbc-block a[href] { @apply link; }
.post .editedby { @apply text-sm italic opacity-70 mt-4; }
.post .title :where(img[src*="gangtags"]) + * {
@apply mb-1;
}
.post i, .post .bbc-spoiler, .post a[href] { @apply inline-block mx-1; }
.pagination a svg {
@apply h-5;
}

View File

@ -34,7 +34,8 @@ if config_env() == :prod do
# ssl: true,
url: database_url,
pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10"),
socket_options: maybe_ipv6
socket_options: maybe_ipv6,
prepare: :unnamed
# The secret key base is used to sign/encrypt cookies and other secrets.
# A default value is used in config/dev.exs and config/test.exs but you
@ -48,7 +49,11 @@ if config_env() == :prod do
You can generate one by calling: mix phx.gen.secret
"""
host = System.get_env("PHX_HOST") || "example.com"
host =
System.get_env("PHX_HOST") ||
"example.com"
|> IO.inspect()
port = String.to_integer(System.get_env("PORT") || "4000")
config :something_erlang, :dns_cluster_query, System.get_env("DNS_CLUSTER_QUERY")
@ -63,6 +68,7 @@ if config_env() == :prod do
ip: {0, 0, 0, 0, 0, 0, 0, 0},
port: port
],
check_origin: [host],
secret_key_base: secret_key_base
# ## SSL Support

View File

@ -38,7 +38,11 @@ defmodule SomethingErlang.AwfulApi.Bookmarks do
info = Meeseeks.one(td, css(".info"))
%{
new_posts: Meeseeks.text(last_seen) |> String.to_integer(),
new_posts:
case Meeseeks.text(last_seen) do
nil -> 0
n -> String.to_integer(n)
end,
thread_title: Meeseeks.text(Meeseeks.one(info, css(".thread_title")))
}
end

View File

@ -35,7 +35,11 @@ defmodule SomethingErlang.AwfulApi.Thread do
end
posts =
for post <- Meeseeks.all(thread, css("table.post:not(.ignored)")) do
for post <- Meeseeks.all(thread, css("table.post")),
post
|> Meeseeks.attr("class")
|> String.contains?("ignored")
|> Kernel.not() do
%{
userinfo: userinfo(post),
postdate: postdate(post),
@ -111,7 +115,11 @@ defmodule SomethingErlang.AwfulApi.Thread do
if class == "sa-smilie" do
{"img", attrs, []}
else
t_attrs = List.keyreplace(attrs, "class", 0, {"class", "img-responsive"})
t_attrs =
attrs
|> fix_attachment_links()
|> List.keyreplace("class", 0, {"class", "img-responsive"})
{"img", [{"loading", "lazy"} | t_attrs], []}
end
end
@ -194,4 +202,15 @@ defmodule SomethingErlang.AwfulApi.Thread do
{"src", src}
], []}
]}
defp fix_attachment_links(attrs) do
{"src", src} = List.keyfind(attrs, "src", 0)
if String.starts_with?(src, "attachment.php") do
List.keyreplace(attrs, "src", 0, {"src", "https://forums.somethingawful.com/" <> src})
|> List.keydelete("alt", 0)
else
attrs
end
end
end

View File

@ -17,7 +17,7 @@ defmodule SomethingErlangWeb.BookmarksLive do
end
defp bookmark(assigns) do
assigns = assign(assigns, :pages, trunc(assigns.post_count / 40))
assigns = assign(assigns, :pages, ceil(assigns.post_count / 40))
~H"""
<div>
@ -37,6 +37,6 @@ defmodule SomethingErlangWeb.BookmarksLive do
{:ok,
socket
|> assign(:page_title, "Bookmarks")
|> assign(:bookmarks, Grover.get_bookmarks!(1) |> dbg())}
|> assign(:bookmarks, Grover.get_bookmarks!(1))}
end
end

View File

@ -69,10 +69,10 @@ defmodule SomethingErlangWeb.ThreadLive do
~H"""
<div class="navbar my-4 bg-base-200">
<div class="flex-1"></div>
<div class="pagination flex-none btn-group grid grid-cols-5">
<div class="pagination join">
<%= for btn <- buttons(@thread) do %>
<.link
class={["btn btn-sm btn-ghost", btn.special]}
class={["btn btn-sm btn-ghost join-item", btn.special]}
navigate={~p"/thread/#{@thread.id}?page=#{btn.page}"}
>
<.label_button label={btn.label} page={btn.page} />
@ -86,8 +86,8 @@ defmodule SomethingErlangWeb.ThreadLive do
defp label_button(%{label: label} = assigns) do
case label do
"«" -> ~H{<.icon name="hero-chevron-double-left-mini" /><%= @page %>}
"" -> ~H{<.icon name="hero-chevron-left-mini" /><%= @page %>}
"" -> ~H{<%= @page %><.icon name="hero-chevron-right-mini" />}
"" -> ~H{<.icon name="hero-chevron-left-mini" />}
"" -> ~H{<.icon name="hero-chevron-right-mini" />}
"»" -> ~H{<%= @page %><.icon name="hero-chevron-double-right-mini" />}
_ -> ~H{<%= @page %>}
end

View File

@ -12,6 +12,7 @@ defmodule SomethingErlangWeb.UserAuth do
@max_age 60 * 60 * 24 * 60
@remember_me_cookie "_something_erlang_web_user_remember_me"
@remember_me_options [sign: true, max_age: @max_age, same_site: "Lax"]
@bbpassword_options [sign: false, max_age: @max_age, same_site: "Lax"]
@doc """
Logs the user in.
@ -38,7 +39,7 @@ defmodule SomethingErlangWeb.UserAuth do
end
defp put_hashcookie_in_session(conn, bbpassword) do
put_resp_cookie(conn, "bbpassword", bbpassword)
put_resp_cookie(conn, "bbpassword", bbpassword, @bbpassword_options)
end
defp maybe_write_remember_me_cookie(conn, token, %{"remember_me" => "true"}) do
@ -185,7 +186,7 @@ defmodule SomethingErlangWeb.UserAuth do
defp mount_current_user(session, socket) do
case session do
%{"user_token" => user_token} ->
%{"user_token" => user_token, "bbpassword" => bbpw} when not is_nil(bbpw) ->
Phoenix.Component.assign_new(socket, :current_user, fn ->
Accounts.get_user_by_session_token(user_token)
end)

View File

@ -59,7 +59,8 @@ defmodule SomethingErlang.MixProject do
{:dns_cluster, "~> 0.1.1"},
{:bandit, "~> 1.2"},
{:meeseeks, "~> 0.17.0"},
{:req, "~> 0.5.0"}
{:req, "~> 0.5.0"},
{:credo, "~> 1.7", only: [:dev, :test], runtime: false}
]
end

View File

@ -1,6 +1,8 @@
%{
"bandit": {:hex, :bandit, "1.5.2", "ed0a41c43a9e529c670d0fd48371db4027e7b80d43b1942893e17deb8bed0540", [:mix], [{:hpax, "~> 0.1.1", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "35ddbdce7e8a2a3c6b5093f7299d70832a43ed2f4a1852885a61d334cab1b4ad"},
"bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"},
"castore": {:hex, :castore, "1.0.7", "b651241514e5f6956028147fe6637f7ac13802537e895a724f90bf3e36ddd1dd", [:mix], [], "hexpm", "da7785a4b0d2a021cd1292a60875a784b6caef71e76bf4917bdee1f390455cf5"},
"credo": {:hex, :credo, "1.7.7", "771445037228f763f9b2afd612b6aa2fd8e28432a95dbbc60d8e03ce71ba4446", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "8bc87496c9aaacdc3f90f01b7b0582467b69b4bd2441fe8aae3109d843cc2f2e"},
"db_connection": {:hex, :db_connection, "2.6.0", "77d835c472b5b67fc4f29556dee74bf511bbafecdcaf98c27d27fa5918152086", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c2f992d15725e721ec7fbc1189d4ecdb8afef76648c746a8e1cad35e3b8a35f3"},
"decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"},
"dns_cluster": {:hex, :dns_cluster, "0.1.3", "0bc20a2c88ed6cc494f2964075c359f8c2d00e1bf25518a6a6c7fd277c9b0c66", [:mix], [], "hexpm", "46cb7c4a1b3e52c7ad4cbe33ca5079fbde4840dedeafca2baf77996c2da1bc33"},