EH Forwarder Bot:在Telegram上收发微信消息

EH Forwarder Bot (以下简称为EFB)是一个Telegram的消息转发机器人框架,目前已经实现的是双向收发微信消息。详细的信息和安装方法,请查阅 官方文档 或是 作者的Blog 。这里只讲一下优缺点。

EFB是Python 3程序,安装在服务器上(一般是VPS)之后,利用 ItChat 提供的网页版微信接口,接收和发送微信信息,同时作为Telegram Bot,向Telegram双向传递微信信息。也就是说,对于微信而言,EFB是一个网页版客户端,而对于Telegram而言,EFB是一个Bot。最终可以实现利用Teleram作为微信客户端收发微信信息。

优点

下面这些优点,有些来自EFB这种工作模式,有些是TG自身的优点。

  • 只要服务器足够稳定,并且手机微信登录状态没有变化,EFB可以一直在线,而与TG客户端是否在线无关。只在EFB第一次登录的时候需要扫码,之后没掉线,自然不用再扫。
  • 使用网页版微信,或者PC、Mac客户端时,最多只能登录一个客户端,加上手机微信,总共两个。用了EFB之后,对于微信而言,只有EFB这一个非手机客户端在线,而TG本身可以多平台多个客户端同时在线。
  • 手机版微信上的聊天记录是完整的,但是非手机版微信客户端上的聊天记录只有在线时那一部分,也无法在客户端之间同步。用了EFB,TG在所有平台上的聊天记录都是同步的,都是完整的。这样等于在全平台上同步、备份了所有聊天记录,包括聊天群的记录,以及公众号文章的标题和题图。
  • 好友撤回的消息,只要被EFB捕捉到了,就能正常看到。
  • 安装好之后,默认所有微信消息(包括群、公众号)会出现在同一个会话中,相当于是微信的时间线。这是个优点还是缺点,每个人的感觉是不一样的。同时,EFB提供了把某个好友或微信群的消息绑定到一个单独TG群组的功能。这样可以平衡一下。
  • TG客户端本身还有一些微信没有的功能。比如,可以集中管理聊天会话中出现的附件、图片、视频、音频等信息,非常方便。可以修改界面主题等。

缺点

缺点也不少,离完美还有很远。而且这些缺点主要是网页版微信的先天不足,或是TG的限制,EFW没有办法改善。

  • 网页版微信无法在聊天群里 @某人 ,EFW自然也不行。
  • 无法撤回消息。
  • 手机微信上的未读数不会自动减少。
  • 由于所有的消息在一个TG会话中,所以,发消息时,只能回复对方发来的消息。如果想主动发消息,需要先手动生成消息头,再回复这个消息头。不太方便,但是不容易发错对象。所以,对于经常联系的好友,还是绑定到单独一个群组比较方便。
  • TG的中文搜索功能非常差,只能搜索空格后的中文字。而且TG不支持导出聊天记录,也没办法导出之后再搜索。虽然有一些利用web客户端或者cli客户端导出聊天记录的做法,但是问题都比较多。所以,虽然TG保存了所有聊天记录,但是搜索不便,也出不来,可用性大大下降。

综上,对于我这种在微信中看的多、讲的少的人而言,EFB是一个不错的选项,虽然有缺陷,但是解决了核心问题,综合体验很不错。

l2tabuen-note

《An essential guide to LaTeX2e usage: Obsolete commands and packages》 是一份20多页的简短文档,介绍了常见的LaTeX错误用法和一些过时命令。 原文是德文,后来被翻译成英文、法文等 (暂无中文版)。一般的发行版中已经包含这份文档,可以使用如下命令打开。

texdoc l2tabuen

以下是不完整的概要,跳过了与德语以及外文字体有关的内容。

  • 不要使用 a4.sty 或者 a4wide.sty ,应该使用类包的 a4paper 选项。

  • 调整页边距时,应该使用 typearea.sty ,或 geometry.sty , 或 vmargin.sty ,不要使用 \oddsidemargin 之类的命令。

  • 如果对TeX不熟悉,不要修改 \hoffset\voffset 命令。

  • 不要直接修改LaTeX的类包文件,如 article.cls

  • 修改行距有三种方法:

    1. 使用 setspace.sty;
    2. 使用LaTeX命令 \linespread{<factor>};
    3. 重新定义 \baselinestretch.
  • 调整段首缩进长度时,不要使用绝对长度,如 mm , 应该使用与字体有关的相对长度,如 em 。 后者不会随着字体大小自动调整,是与依赖于当前使用的字体。 调整要使用LaTeX命令,以便保持良好的兼容性或重新定义。 不要使用 \parindent=1em ,应该使用 \setlength{\parindent}{1em}

  • 调整段落间距,不要使用

\setlength{\parindent}{0pt}
\setlength{\parskip}{\baselineskip}

因为 \parskip 会改变列表环境、目录以及页眉中项目间的间距。 应该使用 parskip.sty 。如果已经使用KOMA-Script中的某一文档类,就不用再调用 parskip.sty 了。

  • 不要在LaTeX文档中使用 $$ ... $$ ,因为这是一个TeX命令, 它会改变段公式的竖直距离,而且 fleqn 选项也会失效。 应该使用 \[ ... \]
\begin{displaymath}
...
\end{displaymath}
  • 使用 \newcommand{\<name>}{...} 定义新命令,不要使用 \def\<name>{...} 。主要是因为 \def 不会检查是否已经有同名的命令。如果之前已经有同名的命令, 不会报错,直接覆盖。重新定义命令时,使用 \renewcommand{\<name>}{...}

  • 过时的改变字体命令已经不适用于新的NFSS字体选择框架, 很多时候无法实现预期的效果。应使用相应的局部命令(仅作用于命令的参数), 或是全局开关命令(其后所有字体都会改变)。过时的命令

    • {\bf ...}, \it, \rm, \sc, \sf, \sl, \tt

    相应的局部命令

    • \textbf{...}, \emph, \texit, \textmd, \textrm, \textsc, \textsf, \textsl, \texttt, \textup

    相应的全局开关命令

    • \bfseries, \em, \itshape, \mdseries, \rmfamily, \scshape, \sffamily, \slshape \ttfamily, \upshape
  • 分式不要用 a \over b, 应该用 \frac{a}{b}

  • 居中不要用 \centerline, 应该用 {\centering ...} 或者

\begin{center}
...
\end{center}
  • 用于插入图片的过时包 epsf.sty, psfig.sty, epsfig.sty 已被 graphics.stygraphicx.sty 代替
  • 用于调整行距的过时包 doublespace.sty 已经被 setspace.sty 代替
  • 用于设置页眉的过时包 fancyheadings.sty 已经被 fancyhdr.sty 代替
  • 不要用 \usepackage{caption}, 应该用 \usepackage{caption}[2004/07/16] 指定使用 caption.sty 的v3.x版
  • 图像、表格等浮动体居中时,建议使用 \centering, 而不是 \begin{center} ... \end{center}, 以避免产生额外的竖直距离。不要这样写:
\begin{figure}
\begin{center}
\includegraphics{bild}
\end{center}
\end{figure}

应该这样写:

\begin{figure}
\centering
\includegraphics{bild}
\end{figure}
  • 附录不再是一个环境,而是用一个命令开始。不要再写成:
\begin{appendix}
\section{Blub}
\end{appendix}

应该这样写:

\appendix
\section{Blub}
  • 对于数学公式,都应该使用 amsmath.sty 包。当使用 amsmath.sty 宏包时,不要再用 displaymath, 直接用 \[ ... \] 即可。 eqnarray, eqnarray* 等环境不支持,应该用 alignalign*.

PWWs-01-10

Trisection of a Line Segment

PWWs-01-10
\documentclass[tikz, border=2pt]{standalone}
\usetikzlibrary{calc}
\usetikzlibrary{math}
\begin{document}
\begin{tikzpicture}[line width=1pt]
  \tikzmath{
    \r = 2;
  }
  \def\template#1; {
    \draw #1 circle [radius=\r];
    \draw #1 ++(\r, 0) circle [radius=\r];
    \draw #1 -- ++(\r, 0);
  }

  \coordinate (O) at (0, 0);
  \template{(O)};
  \node[left] (A) at (O) {$A$};
  \node[right] (B) at ($(O) + (\r, 0)$) {$B$};

  \coordinate (O1) at (3.5*\r, 0);
  \template{(O1)};
  \coordinate (C1) at ($(O1) + (60:\r)$);
  \node[above] () at (C1) {$C$};
  \coordinate (D1) at ($(O1) + (-120:\r)$);
  \node[below] () at (D1) {$D$};
  \draw (C1) -- (D1);

  \coordinate (O2) at (0, -3*\r);
  \template{(O2)};
  \coordinate (B2) at ($(O2) + (\r, 0)$);
  \coordinate (C2) at ($(O2) + (60:\r)$);
  \coordinate (D2) at ($(O2) + (-120:\r)$);
  \coordinate (E2) at ($(O2) + (-60:0.5*\r)$);
  \coordinate (G2) at ($(O2) + (-60:\r)$);
  \draw (C2) -- (D2);
  \draw (D2) -- (B2);
  \draw (O2) -- (G2);
  \node[right=2mm] () at (E2) {$E$};

  \coordinate (O3) at (3.5*\r, -3*\r);
  \template{(O3)};
  \coordinate (B3) at ($(O3) + (\r, 0)$);
  \coordinate (C3) at ($(O3) + (60:\r)$);
  \coordinate (D3) at ($(O3) + (-120:\r)$);
  \coordinate (E3) at ($(O3) + (-60:0.5*\r)$);
  \coordinate (G3) at ($(O3) + (-60:\r)$);
  \draw (C3) -- (D3);
  \draw (D3) -- (B3);
  \draw (O3) -- (G3);
  \draw (E3) -- (C3);
  \draw[dashed] (B3) -- (C3);
  \node[left] () at (O3) {$A$};
  \node[right] () at (B3) {$B$};
  \node[above] () at (C3) {$C$};
  \node[below] () at (D3) {$D$};
  \node[right=2mm] () at (E3) {$E$};
  \node[below right] (F3) at ($(O3) + (0.34*\r, 0)$) {$F$};

  \node[below=2cm, align=center] () at ($(O2) + (2.25*\r, 0)$) {
      $\displaystyle\overline{AF} = \frac{1}{3}\cdot\overline{AB}$
    }
\end{tikzpicture}
\end{document}

PWWs-01-09

Trisection of an Angle in an Infinite Number of Steps

PWWs-01-09
\documentclass[tikz, border=2pt]{standalone}
\usetikzlibrary{calc}
\usetikzlibrary{math}
%\usetikzlibrary{arrows.meta}
\begin{document}
\begin{tikzpicture}[line width=1pt]
  \tikzmath{
    \A = 120;
    \l = 5;
  }
  \coordinate (O) at (0, 0);
  \filldraw (O) circle [radius=2pt];
  \foreach \a in {0, \A}
    \draw (O) -- (\a:\l);
  \foreach \a/\i in {0.5*\A/1, 0.25*\A/2, 0.375*\A/3, 0.3125*\A/4}{
    \draw (O) -- (\a:\l) node[above right] {\i};
  }
  \draw[dashed] (O) -- ++(1/3*\A:1.3*\l);
  \node[below=5mm, align=center] () at ($(O)+(0.3*\l, 0)$) {
      $\displaystyle\frac{1}{3}=\frac{1}{2}-\frac{1}{4}+\frac{1}{8}-\frac{1}{16}+\cdots$
    }
\end{tikzpicture}

\end{document}

PWWs-01-08

The Rolling Circle Squares Itself

PWWs-01-08
\documentclass[tikz, border=2pt]{standalone}
\usetikzlibrary{calc}
\usetikzlibrary{math}
\usetikzlibrary{arrows.meta}
\begin{document}
\begin{tikzpicture}[line width=3pt]
  \tikzmath{
    \r = 3;
    \R = (pi * \r + \r)/2;
    \l = sqrt(pi) * \r;
  }
  \coordinate (O1) at (0, 0);
  \coordinate (O2) at ($(O1)+(pi*\r, 0)$);
  \filldraw[fill=lightgray, draw=black] (O1) circle [radius=\r];
  \filldraw (O1) ++(0, \r) circle [radius=2pt];
  \draw[loosely dashed] (O1) -- +(0, \r);
  \draw[loosely dashed] (O1) -- +(-\r, 0);
  \draw[-{Latex[length=5mm]}] (O1) ++(60:1.2*\r) arc [start angle=60, end angle=30, radius=1.2*\r];
  \draw (O2) circle [radius=\r];
  \filldraw (O2) ++(0, -\r) circle [radius=2pt];
  \draw[loosely dashed] (O2) -- ++(\r, 0) -- ++(0, -\r);
  \draw[loosely dashed] (O2) -- +(0, -\r);
  \draw[dotted, line width=1pt] ($(O1)+(-\r, -\r)$) -- ($(O2)+(2*\r, -\r)$);
  \filldraw[fill=lightgray, draw=black] (O2) ++(0, -\r) rectangle ++(\l, -\l);
  \draw[line width=2pt] (O1) ++(0, -\r) arc [start angle=-180, end angle=0, radius=\R];
\end{tikzpicture}

\end{document}