diff --git a/content/基础篇/4件套多号养号攻略.md b/content/基础篇/4件套多号养号攻略.md new file mode 100644 index 000000000..2947ebb9f --- /dev/null +++ b/content/基础篇/4件套多号养号攻略.md @@ -0,0 +1,101 @@ +--- +title: 4件套多号养号攻略 +keywords: +--- +### 💡 **撸毛的核心技术:养号指南!** + +最近因为 TG 封号的原因,很多小伙伴错过了不少大毛,这让大家深刻明白:**养号是撸毛的核心技术之一**!但市面上分享养号技巧的文章少之又少。 +细节决定成败,今天就为大家梳理一份 **推特、DC、TG 等平台的养号指南**👇: + +--- + +### **养号的关键操作:模仿真实用户** + +✅ **推特养号技巧**: + +- **正常使用**:养号阶段,一周操作两次:点赞、浏览、发文、转推,保持日常活跃。 +- **避免授权过多**:不要让账号全是任务授权。 +- **账号标准**: + 1. 200 粉丝以上; + 2. 注册满 1 年; + 3. 互动不被屏蔽; + 4. 稳定运行,不易封号。 + +✅ **Discord (DC) 养号技巧**: + +- **正常使用**:每周加入 1–2 个 DC 频道,定期在频道内互动,比如发 “gm”。 +- **加好友和创建个人频道**:首次登录后先加好友或创建个人频道,再加入目标频道,可降低风控。 +- **双重验证 (2FA)**:确保账号更安全,避免被风控。 + +✅ **Telegram (TG) 养号技巧**: + +- **日常操作**:一周至少操作 1–2 次。 +- **三大安全设置**:隐藏手机号、开启两步验证、禁止 P2P 语音。 +- **多设备管理**:定期清理 TG 的活跃会话,移除不常用或可疑设备。 + +--- + +### **如何判断 IP 环境是否合格?** + +养号时,IP 是影响账号安全的重要因素。如果遇到以下问题,需检查代理 IP: + +1. 账号频繁触发风控(如频繁验证、发推或加 DC 时被限制)。 +2. 谷歌账号要求验证手机号或绑定邮箱。 +3. 经常触发人机验证,或账号被要求更改辅助邮箱。 + +**检查 IP 质量的方法**: + +- **欺诈风险评分**:通过 [Scamalytics](https://scamalytics.com/) 查询 IP 质量,分数越低越好(建议 20 分以下)。 +- **优质 IP 特征**: + - 独享:IP 仅供自己使用。 + - 干净:IP 未被用于违规操作,不在可疑名单中。 + - 类型:住宅或移动代理 IP,比服务器 IP 更适合社交媒体使用。 + +**注意**: + +- 严禁一个 IP 登录多个账号,建议一个 IP 配对 1–5 个账号。 +- 避免使用廉价代理 IP、站群 IP 或机场 VPN,这些 IP 风险高、稳定性差。 + +--- + +### **四件套养号的注意事项** + +✅ **谷歌邮箱 (Gmail)**: + +- **登录方式**:用辅助邮箱验证,而不是邮箱验证码验证。 +- **及时登录**:半年以上的老号需在 24–48 小时内登录一次。 + +✅ **推特**: + +- **两种登录方式**:Token 登录或 2FA 登录(建议根据账号类型选择)。 +- **日常操作**:不要只在做任务时登录,平时也要发推、点赞、转发,模拟正常用户行为。 + +✅ **Discord**: + +- **首次登录用 Token**:更安全稳定。 +- **下载插件**:[Discord Token 登录插件](https://chromewebstore.google.com/detail/discord-token-login/ealjoeebhfijfimofmecjcjcigmadcai?hl=zh-CN&utm_source=ext_sidebar)。 +- **日常行为**:进入频道后多互动(发言、打招呼等),避免频繁更改密码。 + +✅ **Telegram**: + +- **两步验证**:保护账号安全。 +- **虚拟号码注册**:使用美国 IP 和 TextNow 等虚拟号码替代真实手机号。 +- **操作建议**:尽量不分享资源到 TG,避免安全风险。 + +--- + +### **总结:高效撸毛,从养号开始!** + +1️⃣ **养号的核心在于模仿真实用户**,保持日常活跃,避免过多授权。 +2️⃣ **优化 IP 环境**:独享、干净、高质量的代理 IP 是基础。 +3️⃣ **四件套养号技巧**:推特、DC、TG、谷歌账号的稳定性是撸毛的关键。 + +💡 **稳扎稳打养好号,撸大毛更高效!你还有哪些养号的技巧?欢迎一起讨论!** 👇 + +--- + +📌 **声明** +本文内容转载自 👉 [原文链接](https://mp.weixin.qq.com/s/MYmJmU80rUgg7n1Y9omwYQ)。 +**为防止微信公众号内容被删除或和谐,特此进行了转录保存。** + +--- diff --git a/content/基础篇/区块链空投全解.md b/content/基础篇/区块链空投全解.md new file mode 100644 index 000000000..e8300a5cd --- /dev/null +++ b/content/基础篇/区块链空投全解.md @@ -0,0 +1,33 @@ + +### **为什么发空投?拿到后能做什么?** + +--- + +#### **1️⃣ 什么是区块链空投?** + +空投(Airdrop)是区块链领域的一种营销方式,通过向指定的数字钱包地址发送免费代币或加密货币,让用户直接获得资产。 +**通俗来说**:空投就是项目方免费送加密资产给用户的一种行为。 + +--- + +#### **2️⃣ 项目方为什么要发空投?** + +加密货币是真金白银的,项目方为什么要送给用户呢?主要有以下几个原因: + +1. **宣传推广**:通过空投吸引潜在用户和投资者,提升项目的知名度。 +2. **回馈社区**:奖励早期支持的用户,激励他们在后期为项目贡献力量。 +3. **获取数据吸引投资**:项目方通过增加用户量数据吸引风投(VC)支持,有时会暗示用户使用产品可能会获得空投,这已成为圈内的共识。 + +--- + +#### **3️⃣ 拿到空投后,你可以做什么?** + +当空投代币到账后,你可以选择以下几种方式: + +1. **参与治理**:通过投票影响项目未来的发展方向。 +2. **长期持有**:优质项目的空投代币通常是极低成本筹码,可以等待价格上涨。 +3. **直接变现**:将代币卖出换成原始资本,用于后续投资或其他用途。 + +--- + +💡 **总结**:空投不仅是项目方宣传推广的方式,也是用户积累资本和参与项目生态的绝佳机会。善用空投,让每一个代币都为你创造价值! 🚀 \ No newline at end of file diff --git a/content/基础篇/撸空投4件套多号养号攻略!.md b/content/基础篇/撸空投4件套多号养号攻略!.md deleted file mode 100644 index e72926b26..000000000 --- a/content/基础篇/撸空投4件套多号养号攻略!.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: -keywords: ---- diff --git a/content/科学家养成日记/Chrome浏览器多开.md b/content/科学家养成日记/Chrome浏览器多开.md new file mode 100644 index 000000000..7f3f7efdd --- /dev/null +++ b/content/科学家养成日记/Chrome浏览器多开.md @@ -0,0 +1 @@ +SOON... \ No newline at end of file diff --git a/content/科学家养成日记/Discord Bot.md b/content/科学家养成日记/Discord Bot.md new file mode 100644 index 000000000..7f3f7efdd --- /dev/null +++ b/content/科学家养成日记/Discord Bot.md @@ -0,0 +1 @@ +SOON... \ No newline at end of file diff --git a/docs/features/backlinks.md b/docs/features/backlinks.md index f558f4a5d..6862720e1 100644 --- a/docs/features/backlinks.md +++ b/docs/features/backlinks.md @@ -9,6 +9,7 @@ A backlink for a note is a link from another note to that note. Links in the bac ## Customization - Removing backlinks: delete all usages of `Component.Backlinks()` from `quartz.layout.ts`. +- Hide when empty: hide `Backlinks` if given page doesn't contain any backlinks (default to `true`). To disable this, use `Component.Backlinks({ hideWhenEmpty: false })`. - Component: `quartz/components/Backlinks.tsx` - Style: `quartz/components/styles/backlinks.scss` - Script: `quartz/components/scripts/search.inline.ts` diff --git a/quartz/components/Backlinks.tsx b/quartz/components/Backlinks.tsx index aa412a2e0..e99055e31 100644 --- a/quartz/components/Backlinks.tsx +++ b/quartz/components/Backlinks.tsx @@ -4,33 +4,49 @@ import { resolveRelative, simplifySlug } from "../util/path" import { i18n } from "../i18n" import { classNames } from "../util/lang" -const Backlinks: QuartzComponent = ({ - fileData, - allFiles, - displayClass, - cfg, -}: QuartzComponentProps) => { - const slug = simplifySlug(fileData.slug!) - const backlinkFiles = allFiles.filter((file) => file.links?.includes(slug)) - return ( -
-

{i18n(cfg.locale).components.backlinks.title}

- -
- ) +interface BacklinksOptions { + hideWhenEmpty: boolean } -Backlinks.css = style -export default (() => Backlinks) satisfies QuartzComponentConstructor +const defaultOptions: BacklinksOptions = { + hideWhenEmpty: true, +} + +export default ((opts?: Partial) => { + const options: BacklinksOptions = { ...defaultOptions, ...opts } + + const Backlinks: QuartzComponent = ({ + fileData, + allFiles, + displayClass, + cfg, + }: QuartzComponentProps) => { + const slug = simplifySlug(fileData.slug!) + const backlinkFiles = allFiles.filter((file) => file.links?.includes(slug)) + if (options.hideWhenEmpty && backlinkFiles.length == 0) { + return null + } + return ( +
+

{i18n(cfg.locale).components.backlinks.title}

+ +
+ ) + } + + Backlinks.css = style + + return Backlinks +}) satisfies QuartzComponentConstructor diff --git a/quartz/components/pages/TagContent.tsx b/quartz/components/pages/TagContent.tsx index 5b9fbe282..c703b6524 100644 --- a/quartz/components/pages/TagContent.tsx +++ b/quartz/components/pages/TagContent.tsx @@ -110,7 +110,7 @@ export default ((opts?: Partial) => { return (
-
{content}
+
{content}

{i18n(cfg.locale).pages.tagContent.itemsUnderTag({ count: pages.length })}

diff --git a/quartz/components/scripts/popover.inline.ts b/quartz/components/scripts/popover.inline.ts index 49f438205..b01af0e85 100644 --- a/quartz/components/scripts/popover.inline.ts +++ b/quartz/components/scripts/popover.inline.ts @@ -1,5 +1,6 @@ import { computePosition, flip, inline, shift } from "@floating-ui/dom" import { normalizeRelativeURLs } from "../../util/path" +import { fetchCanonical } from "./util" const p = new DOMParser() async function mouseEnterHandler( @@ -37,7 +38,7 @@ async function mouseEnterHandler( targetUrl.hash = "" targetUrl.search = "" - const response = await fetch(`${targetUrl}`).catch((err) => { + const response = await fetchCanonical(targetUrl).catch((err) => { console.error(err) }) diff --git a/quartz/components/scripts/spa.inline.ts b/quartz/components/scripts/spa.inline.ts index 1790bcabc..df48f0403 100644 --- a/quartz/components/scripts/spa.inline.ts +++ b/quartz/components/scripts/spa.inline.ts @@ -1,5 +1,6 @@ import micromorph from "micromorph" import { FullSlug, RelativeURL, getFullSlug, normalizeRelativeURLs } from "../../util/path" +import { fetchCanonical } from "./util" // adapted from `micromorph` // https://github.com/natemoo-re/micromorph @@ -42,10 +43,24 @@ function notifyNav(url: FullSlug) { const cleanupFns: Set<(...args: any[]) => void> = new Set() window.addCleanup = (fn) => cleanupFns.add(fn) +function startLoading() { + const loadingBar = document.createElement("div") + loadingBar.className = "navigation-progress" + loadingBar.style.width = "0" + if (!document.body.contains(loadingBar)) { + document.body.appendChild(loadingBar) + } + + setTimeout(() => { + loadingBar.style.width = "80%" + }, 100) +} + let p: DOMParser async function navigate(url: URL, isBack: boolean = false) { + startLoading() p = p || new DOMParser() - const contents = await fetch(`${url}`) + const contents = await fetchCanonical(url) .then((res) => { const contentType = res.headers.get("content-type") if (contentType?.startsWith("text/html")) { @@ -104,6 +119,7 @@ async function navigate(url: URL, isBack: boolean = false) { if (!isBack) { history.pushState({}, "", url) } + notifyNav(getFullSlug(window)) delete announcer.dataset.persist } diff --git a/quartz/components/scripts/util.ts b/quartz/components/scripts/util.ts index d0a16c651..c1db8bad5 100644 --- a/quartz/components/scripts/util.ts +++ b/quartz/components/scripts/util.ts @@ -24,3 +24,22 @@ export function removeAllChildren(node: HTMLElement) { node.removeChild(node.firstChild) } } + +// AliasRedirect emits HTML redirects which also have the link[rel="canonical"] +// containing the URL it's redirecting to. +// Extracting it here with regex is _probably_ faster than parsing the entire HTML +// with a DOMParser effectively twice (here and later in the SPA code), even if +// way less robust - we only care about our own generated redirects after all. +const canonicalRegex = // + +export async function fetchCanonical(url: URL): Promise { + const res = await fetch(`${url}`) + if (!res.headers.get("content-type")?.startsWith("text/html")) { + return res + } + // reading the body can only be done once, so we need to clone the response + // to allow the caller to read it if it's was not a redirect + const text = await res.clone().text() + const [_, redirect] = text.match(canonicalRegex) ?? [] + return redirect ? fetch(redirect) : res +} diff --git a/quartz/plugins/emitters/tagPage.tsx b/quartz/plugins/emitters/tagPage.tsx index 066d4ec26..d82a537db 100644 --- a/quartz/plugins/emitters/tagPage.tsx +++ b/quartz/plugins/emitters/tagPage.tsx @@ -105,6 +105,9 @@ export const TagPage: QuartzEmitterPlugin> = (userOpts) const tag = slug.slice("tags/".length) if (tags.has(tag)) { tagDescriptions[tag] = [tree, file] + if (file.data.frontmatter?.title === tag) { + file.data.frontmatter.title = `${i18n(cfg.locale).pages.tagContent.tag}: ${tag}` + } } } } diff --git a/quartz/styles/base.scss b/quartz/styles/base.scss index 00893d5b1..e46c383ad 100644 --- a/quartz/styles/base.scss +++ b/quartz/styles/base.scss @@ -607,4 +607,15 @@ iframe.pdf { height: 100%; width: 100%; border-radius: 5px; -} \ No newline at end of file +} + +.navigation-progress { + position: fixed; + top: 0; + left: 0; + width: 0; + height: 3px; + background: var(--secondary); + transition: width 0.2s ease; + z-index: 9999; +}