Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings
This repository was archived by the owner on Nov 8, 2022. It is now read-only.

Commite9af42e

Browse files
authored
chore(debug): create post (#447)
* chore(debug): add log* fix(digest): use list as backup digest source* chore: bump version* chore: debug prod* chore: debug prod* chore: debug prod* chore: debug prod* chore: clean up
1 parentc13f59d commite9af42e

File tree

15 files changed

+90
-31
lines changed

15 files changed

+90
-31
lines changed

‎Makefile‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,8 @@ console.dev:
201201
MIX_ENV=dev iex --erl"-kernel shell_history enabled" -S mix
202202
console.mock:
203203
MIX_ENV=mock iex --erl"-kernel shell_history enabled" -S mix
204+
console.test:
205+
MIX_ENV=test iex --erl"-kernel shell_history enabled" -S mix
204206

205207
# dashboard
206208
dashboard.help:

‎config/test.exs‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,6 @@ config :groupher_server, GroupherServer.Mailer, adapter: Bamboo.TestAdapter
3535

3636
config:groupher_server,:audit,
3737
token:"24.aa6fb4e4018c371e9ed228db5bea3ec0.2592000.1641816180.282335-25148796"
38+
39+
config:groupher_server,:plausible,
40+
token:"tDsEjaIBqmfVpkKByebYgrCs1Kl1V3N3prFACyFJq33eeEumg8hAFgm-3ZQamwAq"
6.54 KB
Binary file not shown.

‎lib/helper/audit_bot.ex‎

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ defmodule Helper.AuditBot do
2424
@conclusionOK1
2525
@conclusionMaybe3
2626

27-
@tokenget_config(:audit,:token)
27+
#@token get_config(:audit, :token)
2828

2929
@url"https://aip.baidubce.com"
30-
@endpoint"#{@url}/rest/2.0/solution/v1/text_censor/v2/user_defined?access_token=#{@token}"
30+
#@endpoint "#{@url}/rest/2.0/solution/v1/text_censor/v2/user_defined?access_token=#{@token}"
3131
@wrong_endpoint"#{@url}/rest/2.0/solution/v1/text_censor/v2/user_defined?access_token=wrong"
3232

3333
defanalysis(:text,text)do
@@ -37,7 +37,7 @@ defmodule Helper.AuditBot do
3737

3838
text=text|>HtmlSanitizeEx.strip_tags()
3939

40-
with{:ok,result}<-HTTPoison.post(@endpoint,{:form,[text:text]},headers)do
40+
with{:ok,result}<-HTTPoison.post(get_endpoint(),{:form,[text:text]},headers)do
4141
parse_result(result)
4242
end
4343
end
@@ -138,4 +138,17 @@ defmodule Helper.AuditBot do
138138
defptransSubType(7),do:"恶意 / 软文推广"
139139
defptransSubType(8),do:"恶意 / 软文推广"
140140
defptransSubType(_),do:"疑似灌水"
141+
142+
defpget_endpoint()do
143+
token=get_config(:audit,:token)
144+
"#{@url}/rest/2.0/solution/v1/text_censor/v2/user_defined?access_token=#{token}"
145+
end
146+
147+
deftest()do
148+
text="""
149+
<div class="article-viewer-wrapper"><h2 id="block-h5nAl">关于产品</h2><p id="block-ADGMH">CoderPlanets 是一个开源的、面向 IT 垂直领域的中文社区平台,提供类似于 Reddit 社区,ProductHunt 作品发布,Medium 博客平台以及各种自以为是的、奇奇怪怪的服务。</p><h2 id="block-6LrrL">关于为什么</h2><h3 id="block-D4y6q">1. 为什么是社区?</h3><p id="block-ktgV6">中文社区,尤其是技术社区的现状和一些平台各种让人窒息的骚操作我就不赘述了,这几年关注产品多一些,心中渐渐升起一轮疑问:中国的 Reddit, ProductHunt, Medium 们怎么都没有做起来(如果曾经有的话)?</p><p id="block-Zb6Pc">我平时喜欢踢球,有时候觉得中文社区很多现象和中国足球还挺像的 — 足协监管不行,教练不行,草皮不行,球迷文化不行,市场环境不行,日韩崛起之前黄种人也不行,总之各种大字报式的不得行,就是没人说技战术本身,时至今日国足都被越南按着摩擦了,不缺技术缺的是xx(可能是钙?)的论调依然充斥耳边。</p><p id="block-PAONM">纯主观感受,Github, StackOverflow, HN, Reddit, Medium, ProductHunt, IndieHackers, Dev.to, Discord 哪怕是 Discourse / Flarum , 这些外网常见的开发者交流平台,在国内真的很少有在产品力和情怀上能与之接近的产品。除了足协和草皮之外,有没有可能,我只是说有可能(音量 0.5%),<b>我们本身的产品力不够好?</b>Github 不仅只是一个简单的托管平台,他本身优秀的设计就大大促进了开源运动的推广和发展,更像是一种共生关系。</p><p id="block-HGMHN">产品力不够的情况下一味去“运营推广”,我不否认这很重要,但这总会让我联想起国足明明技战术水平不行,总爱强调个精神意志力一样,挨打不立正,[不能说没道理,但就是怪怪的].jpg。</p><p id="block-vIS4g">所以为什么是社区?我想尝试一个最朴素而真诚的想法:通过认真把社区产品本身打磨好(当然目前还差的很远),剧情的发展会不会有一些不同?</p><p id="block-FV84Y">退两步从现实角度来说,根据上个月 Github 公布的数据,仅来自国内的注册用户就已经超过了 755 万,如此庞大的开发者群体,口味一定是多种多样的,参差多态乃幸福本源,谁也不希望出去外面吃饭,街上只有一两家餐厅可供选择吧?</p><h3 id="block-BDEEe">2. 为什么是中文?</h3><p id="block-PiHru">因为是母语啊。文字之间,很多时候是很难用非母语去交流的,这里语境的交流,不是指能看懂文档、README,能提 issue 或者参与 StackOverflow 之类说明书式的、功能性的交流,而是指那种能浸润情感的,见梗会意一目 n 行的,有幽默感的那种,哦,正常交流 。。不长期浸淫双方的文化背景,这其实是非常困难的。很多时候我们只是单向的被辐射。</p><p id="block-zIPK1">国内技术圈子时不时有种莫名其妙的、动辄鄙视用中文交流的政治正确,有些人,那确实是猛龙过江学贯中西咱服了,但也有些人,等慕名顺着网线去拜读他们在外网的 Post,会发现很多就停留在手语比划的层面,整个感觉和商场里那种导航机器人差不多,其实挺没劲的,无聊的要死。</p><p id="block-epOV2">往狭义上杠,这些叫沟通,不是交流。语言文字远不仅仅只是所谓的“沟通的工具”,这种不知道哪儿冒出来的言论实在是太过贬低了。</p><p id="block-1Q0Rg">隔行不隔理。自己的联赛、青训拉跨,整体上竞技水平是不可能高的,这是普世性的基础共识,不是简单的请进派出几个大V就能解决,更不是谩骂抱怨能改善的。自嘲自黑无法赢得尊重。环境的改变不能只靠羊教练,大头还得是基层的组织参与,训练比赛的日常点滴等等。当然这跑题了。。</p><h2 id="block-A21M8">关于域名</h2><p id="block-LLzRj">我是一个三体迷,对宇宙中的各种都市传说感兴趣。planets 这个域名是我在 N 刷 《星际穿越》的间隙阴差阳错捡来的(虽然后来我确实花了很多心思在网站上加入了<a href="https://coderplanets.com/post/254">各种宇宙元素</a>),并没有什么深思熟虑,也不是要模仿谁。</p><p id="block-SkU1G">域名,尤其是有意义的短域名,是非常稀缺的资源,选择一个两个单词组合的长域名也确实存在客观条件的限制。所以为了方便各位“懒人”,也同时启用了一个好记的短域名:cper.co, ,目前用在站内文章的分享模块。</p><h2 id="block-iFFdD">关于合规</h2><p id="block-MBZzl">社区平台模式在国内几乎是个“伏地魔”一般的话题,说起来都是闻风丧胆,但实际见过做过的人却又少的可怜,问就是有个朋友语焉不详。真正的参与者因为某些原因似乎也比较避讳这个话题 -- 至少我发给各大社区的咨询邮件都石沉大海了。。</p><p id="block-GqiwN">言论的管制当然会降低讨论话题的多样性和深度,就好比在路上开车,谁也不会到红灯底下才瞬间停止,都是老远就踩了刹车。但是随着年龄和阅历的增长,我也能渐渐理解这种做法,这并不是简单的非黑即白的事情,有各方面的因素。</p><p id="block-tuGyu">垂直领域的社区情况要好一些,公司、ICP 备案、敏感词检测该有的都有,其他证件资质在目前还不需要,需要我也会尽快补齐,这其中的经验过程都会同步到社区中以供参考,就不展开了。</p><h2 id="block-rU3Hd">关于盈利</h2><p id="block-op94B">CP 从产品形态上借鉴了很多 Reddit 的元素,但在盈利模式上更向往 “Medium” 的 membership / SaaS、或 “Shopify” 那种工具文化的模式。</p><p id="block-GoqPt">传统的外挂式自动化广告对于文字类网站的体验降维是灾难性的 — 想象一下你在一家装修精美的餐厅(比如 Medium)正在享受晚餐(阅读技术资料),旁边突然有个油嘴滑舌的房产中介向你喋喋不休(侧边栏设计拙劣的双十一服务器广告传单)是什么体验?是,你可以选择带上降噪耳机(AdBlock)不去看 Ta,继续用餐,但问题的源头是,这家餐厅为什么要允许这些人进来发传单? 我又为什么要忍受这样糟糕的服务?</p><p id="block-dhtZm">p.s: 我对房产中介没有不敬的意思,只是打个比喻。也顺便说一下 AdBlock 不违法,但是很不道德。至于说餐厅是收费的网站是免费的,你可以把餐厅的比喻换成书店之类的场所,这就不重复了,不是重点。</p><p id="block-Gh9PA">Medium 作为北美流量前 20 的网站,你很难在上面看到像国内网站那种塞满屏幕的传单式广告,相反它排版优雅大量留白、专注阅读本身的体验,Shopify 那种美好的工具文化的产物就更不用说了。</p><p id="block-PUF4U">我想表达的是,盈利模式在很大程度上会影响产品形态和用户体验。广告模式是广泛存在,但它未必是合理的、适合所有场景的,互联网并不是只有靠广告收益才能生存,至少 Medium 和 Shopify 证明了还有其他的被主流市场验证过的路可以尝试。</p><p id="block-DX4Pn">CoderPlanets 既是提供社区服务的平台,本身也是建立社区的工具。</p><h2 id="block-euCjx">关于团队</h2><p id="block-lT96O">目前团队在产品开发上只有我一人。 不过得益于现在基础设施、开发工具和资源的成熟丰富,对于 CRUD 层面的工作,一个人也可以做到所谓的“全栈”,具体到社区这种周期很长的项目上,前期人少倒也不是坏事 — 回头来看,很多想法初期其实是非常模糊的,是在做的过程中才慢慢连点成线,逐渐变的清晰起来,这个过程需要时间反复的打磨,通常还伴随着破坏性的重构,用传统的产品-设计-开发那种“下周发版”的流水线搞法,几乎注定扑街,沟通成本真的是非常大的成本。缺点就是慢,望山跑死马,需要足够的耐心、体力和相信自己的直觉。。</p><p id="block-bXc9t">目前项目已经度过前期从 0 到 1,虽然技术产品等各方面框架趋于清晰,但各种细节,内容和管理后勤支撑等方面还有大量工作量 ,如果你对社区的产品形态,技术,设计,维护治理等方面感兴趣,欢迎各种形式的参与。</p><h2 id="block-mrk3D">开放透明</h2><p id="block-38w1U">本站除源代码开源在 <a href="https://github.com/coderplanets">Github</a> 上以外,<a href="https://plausible.io/coderplanets.com">流量统计数据</a>也是完全公开的。同时,借鉴真实世界的运行模式,每个子社区都采用志愿者协助的自治模式 -- 细节很多,这里就不展开了。</p><p id="block-2zKdQ">p.s: 流量统计采用的服务商是开源的,对隐私友好的 <a href="https://plausible.io/">Plausible</a> ,它同样使用了小众的 Elixir 开发,我在项目上借鉴过它的一些写法。</p><h2 id="block-WdDFN">发展规划</h2><p id="block-exhYo">最迫切的就是收集各位用户的反馈建议,大的方向是社区的 SaaS 化和工具化。需要说明的是,所有的产品设计都是围绕专业的垂直领域需求而展开的,过去现在和未来都不会面向所有人,我没有那个技术、资源以及意愿。</p><p id="block-nQEBJ">目前这个项目有很多部分还是半成品,TodoList 上更是有接近 4 位数的细节条目等待完成,因此至少到年前,都会处于一个忙碌的修修补补的状态。</p><p id="block-K1vzO">最后,Designing a product from scratch is always hard. 也许再挺不了几年,也许经常会被打脸,但这就是我此时此刻,作为基层代码工人,近年来对社区论坛这个”古董概念”的一些不成熟的想法、摸索和实践。项目中未完成和闭门造车的地方一言难尽,期待能和大家一起讨论完善。</p></div>
150+
"""
151+
152+
analysis(:text,text)
153+
end
141154
end

‎lib/helper/converter/article.ex‎

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ defmodule Helper.Converter.Article do
2929
with{:ok,body_map}<-to_editor_map(body),
3030
{:ok,body_html}<-EditorToHTML.to_html(body_map),
3131
{:ok,body_encode}<-Jason.encode(body_map)do
32-
%{body:body_encode,body_html:body_html,body_map:body_map}|>done
32+
%{body:body_encode,body_html:body_html,body_map:body_map}
33+
|>done
3334
end
3435
end
3536

@@ -39,18 +40,47 @@ defmodule Helper.Converter.Article do
3940
parse digest by concat all the paragraph blocks
4041
"""
4142
defparse_digest(%{"blocks"=>blocks}=body_map)whenis_map(body_map)do
42-
paragraph_blocks=Enum.filter(blocks,&(&1["type"]=="paragraph"))
43+
digest_blocks=Enum.filter(blocks,&(&1["type"]=="paragraph"))
4344

44-
Enum.reduce(paragraph_blocks,"",fnblock,acc->
45+
Enum.reduce(digest_blocks,"",fnblock,acc->
4546
text=block["data"]["text"]|>HtmlSanitizer.strip_all_tags()
4647
acc<>text<>" "
4748
end)
4849
|>String.trim_trailing()
50+
|>parse_other_blocks_ifneed(blocks)
4951
|>String.slice(0,@article_digest_length)
5052
|>done
5153
end
5254

53-
defparse_digest(_),do:{:ok,"unknow digest"}
55+
defparse_digest(_),do:{:ok,"无可预览摘要"}
56+
57+
# 如果文章里没有段落,可以使用列表内容(如果有的话)作为预览内容
58+
defpparse_other_blocks_ifneed("",blocks)do
59+
list_blocks=Enum.filter(blocks,&(&1["type"]=="list"))
60+
61+
digest=
62+
caselist_blocksdo
63+
[]->
64+
"无可预览摘要"
65+
66+
_->
67+
digest_block=list_blocks|>List.first()
68+
69+
Enum.reduce(digest_block["data"]["items"],"",fnitem,acc->
70+
text=item["text"]
71+
acc<>text<>" "
72+
end)
73+
|>String.trim_trailing()
74+
|>HtmlSanitizer.strip_all_tags()
75+
|>String.slice(0,@article_digest_length)
76+
end
77+
78+
digest
79+
end
80+
81+
defpparse_other_blocks_ifneed(paragraph_digest,_blocks)do
82+
paragraph_digest
83+
end
5484

5585
@doc"""
5686
decode article body string to editor map and assign id for each block

‎lib/helper/converter/editor_to_html/class.ex‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ defmodule Helper.Converter.EditorToHTML.Class do
4040
"label__red"=>"list-label__red",
4141
"label__green"=>"list-label__green",
4242
"label__warn"=>"list-label__warn",
43-
"unorder_list_prefix"=>"list__item-unorder-prefix",
43+
"unordered_list_prefix"=>"list__item-unorder-prefix",
4444
"order_list_prefix"=>"list__item-order-prefix",
4545
"list_item"=>"list-item",
4646
"checklist_item"=>"list-checklist__item",

‎lib/helper/converter/editor_to_html/frags/list.ex‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ defmodule Helper.Converter.EditorToHTML.Frags.List do
99

1010
@classget_in(Class.article(),["list"])
1111

12-
@specget_item(:checklist|:unorder_list|:order_list,T.editor_list_item())::T.html()
12+
@specget_item(:checklist|:unordered_list|:order_list,T.editor_list_item())::T.html()
1313
defget_item(
14-
:unorder_list,
14+
:unordered_list,
1515
%{
1616
"hideLabel"=>hide_label,
1717
"indent"=>indent,
@@ -20,7 +20,7 @@ defmodule Helper.Converter.EditorToHTML.Frags.List do
2020
"text"=>text
2121
}
2222
)do
23-
prefix_frag=frag(:unorder_list_prefix)
23+
prefix_frag=frag(:unordered_list_prefix)
2424
label_frag=ifhide_label,do:"",else:frag(:label,label_type,indent,label)
2525
text_frag=frag(:text,text)
2626

@@ -91,9 +91,9 @@ defmodule Helper.Converter.EditorToHTML.Frags.List do
9191
</div>)
9292
end
9393

94-
@specfrag(:unorder_list_prefix)::T.html()
95-
deffrag(:unorder_list_prefix)do
96-
~s(<divpl-s1">#{@class["unorder_list_prefix"]}"></div>)
94+
@specfrag(:unordered_list_prefix)::T.html()
95+
deffrag(:unordered_list_prefix)do
96+
~s(<divpl-s1">#{@class["unordered_list_prefix"]}"></div>)
9797
end
9898

9999
@specfrag(:order_list_prefix,String.t())::T.html()

‎lib/helper/converter/editor_to_html/validator/editor_schema.ex‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ defmodule Helper.Converter.EditorToHTML.Validator.EditorSchema do
88
@valid_quote_mode["short","long"]
99

1010
# list
11-
@valid_list_mode["checklist","order_list","unorder_list"]
12-
@valid_list_label_type["green","red","warn","default"]
11+
@valid_list_mode["checklist","order_list","unordered_list"]
12+
@valid_list_label_type["green","red","warn","default",nil]
1313
@valid_list_indent[0,1,2,3]
1414

1515
# table
@@ -66,7 +66,7 @@ defmodule Helper.Converter.EditorToHTML.Validator.EditorSchema do
6666
item:%{
6767
"checked"=>[:boolean],
6868
"hideLabel"=>[:boolean],
69-
"label"=>[:string],
69+
"label"=>[:string,required:false],
7070
"labelType"=>[enum:@valid_list_label_type],
7171
"prefixIndex"=>[:string,required:false],
7272
"indent"=>[enum:@valid_list_indent],

‎lib/helper/converter/md_to_editor.ex‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ defmodule Helper.Converter.MdToEditor do
108108
%{
109109
type:"list",
110110
data:%{
111-
mode:"unorder_list",
111+
mode:"unordered_list",
112112
items:items
113113
}
114114
}

‎lib/helper/plausible.ex‎

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,33 +13,36 @@ defmodule Helper.Plausible do
1313
@timeout_limit4000
1414

1515
@site_id"coderplanets.com"
16-
@tokenget_config(:plausible,:token)
16+
#@token get_config(:plausible, :token)
1717

1818
@cache_pool:online_status
1919

2020
plug(Tesla.Middleware.BaseUrl,@endpoint)
21-
plug(Tesla.Middleware.Headers,[{"Authorization","Bearer#{@token}"}])
21+
#plug(Tesla.Middleware.Headers, [{"Authorization", "Bearer #{@token}"}])
2222
plug(Tesla.Middleware.Retry,delay:200,max_retries:2)
2323
plug(Tesla.Middleware.Timeout,timeout:@timeout_limit)
2424
plug(Tesla.Middleware.JSON)
2525

26+
defpget_token(),do:get_config(:plausible,:token)
27+
2628
defrealtime_visitors()do
2729
query=[site_id:@site_id]
2830
path="#{@realtime_visitors_query}"
2931
# NOTICE: DO NOT use Tesla.get, otherwise the middleware will not woking
3032
# see https://github.com/teamon/tesla/issues/88
3133
# with true <- Mix.env() !== :test do
32-
with{:ok,%{body:body}}<-get(path,query:query)do
34+
with{:ok,%{body:body}}<-
35+
get(path,query:query,headers:[{"Authorization","Bearer#{get_token()}"}])do
3336
caseis_number(body)do
3437
true->
3538
Cache.put(@cache_pool,:realtime_visitors,body)
36-
{:ok,body}
39+
{:ok,Enum.max([body,1])}
3740

3841
false->
3942
{:ok,1}
4043
end
4144
else
42-
error->
45+
_->
4346
Cache.put(@cache_pool,:realtime_visitors,1)
4447
{:ok,1}
4548
end

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp