10
26
2015
52

使用 Wine 运行 QQ 轻聊版

2021年07月11日更新:轻聊版已经不可用。

截图

Wine QQ 轻聊版 7.5

注:图中的文字方框已经解决。

安装使用

测试过的 Wine 版本为 1.7.52、1.7.54。1.7.53 是坏的。1.6 系列大概跑不起来。

Wine 环境下载地址签名,使用的新 key)。压缩包中安装的是官方完整版的 QQ 轻聊版 7.7(安装文件名 QQ7.7Light.exe)。

文件最后更新于2016年1月29日

  1. 下载文件并解压、找个地方放好(移动之后启动图标会失效)。
  2. 如果系统上没有 simsun.ttc 字体,去网上下一个放到 ~/.fonts 中。或者到解压出来的 Wine 环境里 winetricks fakechinese 也行。
  3. 运行解压出来的目录下边的install-icon.sh脚本来安装启动图标

安装好之后,在你通常找所有已安装的应用程序的地方就可以找到「Wine QQ 轻聊版」的启动图标了。你也可以运行解压出来的目录下边的qq脚本来启动,但必须在那个目录下运行。

在火狐里点击「加入QQ群」之类tencent://协议的链接时,也是可以调用到的哦~不过即使已经登录,也会开启新的 QQ 登录界面。但是不这样又会有更严重的问题,所以凑合着用吧。

其它调整,如使 QQ 无限制地访问文件系统(默认只允许访问 C 盘)、更改一些文件的存放位置、字体选择与渲染选项,请自行修改。想要 Flash 的也请自己 winetricks 安装。

已知问题

  • 记不住密码
  • 密码框需要耐心地点几下才能开始输入
  • 表情图片只有启动后的第一次使用时正常,之后弹出窗口的内容不能正常显示
  • 窗口周围部分的显示不正常(可能和 Awesome 有关)
  • 使用 Windows 内建的移动窗口功能(拖动窗口边框、标题栏)时可能会导致窗口开始避开鼠标指针(可能和 Awesome 有关)
  • 部分群文件下载能够成功,但是界面上看到的进度一直是0字节未完成状态(比较小的文件不受影响)

制作步骤

由于之前的 TM2013 已经很久没更新了,有很多功能都跟不上(比如群公告、语音消息等),所以我又 Wine 了新版本。QQ 轻聊版感觉就是 QQ 标准版去掉了广告,不用付费开通会员来去掉那些干扰广告了。

首先 winetricks 一下:

winetricks sandbox riched20

然后把 Windows 版本设置为Windows 8.1(大于 XP 即可)。不设置安装不上,因为缺少CmRegisterCallback函数。

将 QQ7.5Light.exe 安装文件链接到 C 盘内,安装。

再打开 winecfg,作如下设置:

  • 设置 Windows 版本为 Windows XP
  • 「增加程序设置」,找到 drive_c/Program Files/Common Files/Tencent/QQProtect/Bin/QQProtect.exe 文件,设置其版本为 Windows 8.1(不然会出错)
  • 回到「默认设置」,切换到「函数库」标签,添加「txplatform.exe」「函数库顶替」,并且设置为「禁用」

禁用 TXPlatform.exe 会导致tencent://链接不能在已有的 QQ 里打开。但是启用它会导致登录不了或者退出不了(卡住)的情况。

从 Windows 上复制 iphlpapi.dll,放到 system32 目录,并设置原装优先,以绕过「查找」对话框打开时卡死的问题。

修改system.reg注册表文件,设置 Tahoma 的 FontLink 项(不然部分文字乱码):

[Software\\Microsoft\\Windows NT\\CurrentVersion\\FontLink\\SystemLink] 1420549548 0
"Tahoma"="simsun.ttc,SimSun"

当然你也可以把这里的宋体替换成你想要的任何字体。

另外,这里有人在制作并维护 Wine QQ 精简版。

2015年11月12日更新:更新到 QQ 轻聊版 7.7。旧版用户以 Windows 8.1 版本号来运行 7.7 的安装程序即可更新。

旧的 QQ 轻聊版 7.5 Wine 环境下载地址签名,使用的新 key)。压缩包中安装的是官方完整版的 QQ 轻聊版 7.5(安装文件名 QQ7.5Light.exe)。

2016年3月5日更新:请禁用QQProtectUpd.exe或者将drive_c/Program Files/Common Files/Tencent/QQProtect目录及其下的所有文件设置为只读(chmod -R -w 目录),以免 QQ 自动后台更新之后崩溃。

Category: Linux | Tags: linux windows QQ wine 腾讯
3
24
2013
24

使用 Wine 运行腾讯 TM

TM 是腾讯出品的一款与 QQ 互通的即时通讯产品。用起来就是瘦过身、去过广告的 QQ。TM2009Beta3.4 是目前最新的、也是唯一能够正常使用的 TM 版本。目前最新版本为 TM2013preview1,按如下方法也可使用。TM官网。最新的 preview2 版本无法安装,请使用此地址下载 preview1 版本。

我这里使用的是 Wine 1.5.26。相比之前我运行修改版 QQ 2010 时使用的版本,此版本在 TM 输入密码时不会崩溃、没有黑影等。在线后数秒内自动变成离开状态的问题依然存在。

不像 Winhex 或者 Beyond Compare,TM / QQ 并无法在 Wine 上直接运行,需要使用 winetricks 命令安装一些东西。细节如下:

首先,因为需要使用 winetricks 安装一些东西,为干净考虑,可为 TM 设置单独的 prefix,即

$ export WINEPREFIX=$HOME/.wine4tm

我这里是 64 位的 Arch Linux,因此需要设置 Wine 使用 32 位 Windows 环境:

$ export WINEARCH=win32

注意这种情况下,不要建立未初始化的$WINEPREFIX目录。运行一下winecfg什么的,让 Wine 自己建立之。

因为是 32 位环境,所以有些库可能需要手动安装,比如 Arch 下我手动安装了以下 32 位库:

lib32-libpng lib32-libjpeg-turbo lib32-mpg123 lib32-libxml2

初次运行某个 exe 文件时,注意下终端的输出。如果其中提到某个.so文件没有找到,那么就手动安装上吧。Arch 下查询需要安装的包的方法是,使用 pkgfile 命令查询该文件名,如:

$ pkgfile libpng15.so.15
extra/libpng
multilib/lib32-libpng

lib32-开头那个即是需要安装的软件包。安装之后并不需要重新运行该 exe 文件,除非它已经导致了问题。

lib32-libpng不安装会导致部分界面显示异常,lib32-libjpeg-turbo不安装可能导致好友发送的图片无法显示。

然后使用 wine 运行 TM2009Beta3.exe 这个安装文件。同时可以开始 winetricks 相关工作。

需要使用 winetricks 安装的组件如下:

  1. riched20

    此组件将解决登陆成功后 TM 崩溃的问题。相关bug报告在此。

  2. ie6

    此组件将解决编辑消息时的崩溃。其错误消息为:

    ###!!! ABORT: Main-thread-only object used off the main thread: file /build/wine-mozilla-1.9/xpcom/base/nsCycleCollector.cpp, line 1151
    

    从 winetricks 提供的地址下载 ie6 很慢,并且有些限制。可以通过 Google 搜索「msie60.exe」得到另外的下载链接,比如这个

  3. mfc42

    此组件将解决启动时 TM 界面中的黄条警告,以及其它一些问题。

安装完毕后,在点击链接时 winebrowser 会崩溃。使用 Wine 内建的「urlmon.dll」即可。设置方法是,打开winecfg,切换到「函数库」选项卡,在「已有的函数库顶替」中编辑「urlmon.dll」项,设置其使用「内建」版本。

搞完这些,TM2009 就可以使用啦!来张高清全屏截图——

已知问题:

  • 截图仅能截取一个屏幕。快捷键仅在 Wine 程序拥有焦点时可以工作
  • 接收图片时的动画不正常
  • 输入法光标跟随无效。fcitx 输入框总是位于输入框下方(这里有补丁,据说可以修正这个问题)
  • 在 Awesome 下(特别是双显示器的扩展屏上时),鼠标拖动窗口上边缘可能导致窗口乱跑
  • 可能会卡死(线程死锁,wine 的已知 bug),特别是在打开聊天记录时
  • Awesome 下最大化等同于全屏,wibox 被遮挡
  • 数秒后会自动变成离开状态此问题已经在 Wine 1.7.6 中修复

语音和视频暂未测试。远程协助基本正常。

重要提示:TM 的截屏图片是以 JPEG 格式发送和显示的,会造成截图模糊、失真。(尽管截屏并保存的话是 PNG,从其截屏功能或者从剪贴板粘贴的、发送到会话的图片是 JPEG。)常见的可接受的截图格式只有 PNG、GIF 或 BMP。JPEG 只适合照片这种取自自然而非生成的图像。

Category: Linux | Tags: linux QQ windows wine TM 腾讯
12
28
2011
11

利用脚本提升 Wine QQ 登录体验

我从某处下载的QQ2010,其它都好,就是登录时焦点在密码框时,QQ就会崩溃。解决办法是使用QQ自带的软键盘输入密码。但在这个「半字母顺序」排列软键盘上找需要的需要实在费事。作为一名 Linuxer,我自然得想办法将其自动化。

很久之前就已经看到这个Xpresser软件,但可惜的是,它在Arch下跑不起来。但我从中学到了简单的图像匹配,再加上自己对 Xtest 的了解,解决方案呼之欲出。

本来是三个月前就打算写篇文章的,因各种原因迟迟未写。现在因为各种原因再次折腾这家伙,还是写出来分享一下吧。使用OpenCV做图像匹配部分我就不写了,有兴趣的自己去看 Xpresser 或者 winterpy 中的代码。

首先,介绍一下依赖。本脚本依赖众多的东西,其中我自己写的部分在 winterpy 里有,主要是 OpenCV 图像匹配,以及之前写过的 Xtest 调用使用 GDK 截图。最终,我利用它们写成了 xauto.py 库,功能还十分欠缺,但自动登录Wine QQ足够了,因为我做这些的主要目的就是这可恶的QQ。

#!/usr/bin/env python3
# vim:fileencoding=utf-8

import os
import sys
from xauto import XAuto, Image

QQNo = 'YourQQNo'
QQPwd = 'YourQQPassword'

def main():
  if os.fork() == 0:
    if os.fork() == 0:
      os.execlp('rwine', 'rwine')
    else:
      sys.exit()
  os.chdir(os.path.split(sys.argv[0])[0])

  rect = (20, 150, 500, 500)
  xa = XAuto()
  w, h = xa.screensize
  target_w, target_h = 500, 300
  w, h = w - target_w, h - target_h
  w, h = w // 2, h // 2
  center = (w, h, target_w, target_w)
  xa.default_rect = center

  xa.find_and_click('ok.png', repeat=10) or sys.exit('click 确定')
  xa.find_and_click('qq.png', repeat=10) or sys.exit('find qq no input')
  xa.wait(1)

  for k in QQNo:
    xa.key(k)

  xa.wait(0.4)
  pwd_pos = xa.find('input_pwd.png')
  xa.click(pwd_pos)
  caps = Image('caps.png')
  xa.wait(0.4)
  for ch in QQPwd:
    xa.find_and_click('%s.png' % ch) or sys.exit(2)
    xa.wait(0.1)
    xa.find_and_moveto(caps)
    xa.wait(0.1)
  xa.moveto(pwd_pos)
  xa.wait(0.4)
  xa.find_and_click('login.png')

if __name__ == '__main__':
  main()

几点说明:

  1. 执行以下命令禁止QQ记住用户信息,这样再次启动时焦点会在输入QQ号的地方而不是会导致崩溃的密码框。如果你使用我给的压缩包的话应该可以跳过。
    rm -rf Users/All\ Users
    mkdir Users/All\ Users
    chmod -w Users/All\ Users
    
  2. 需要 wine 1.3.32 或更低,以及 wine_gecko 1.3 或更低。新版本在调用 IE 的组件进行显示时会崩溃,这包括「消息管理器」、「查看聊天历史」、「聊天窗口」的侧栏等。
  3. 我执行的是自己包装过的具有隐私保护功能的「rwine」程序。不过也不是特别安全,QQ仍能够访问剪贴板、截图等。
  4. 密码当然是明文保存。你觉得有必要折腾的话可以自己修改。
  5. 程序中需要的图片自己截。应该很容易知道应该截哪里。这样也避免了字体不同导致图像匹配失败。
  6. 此版本的 QQ 可以在这里下载:115 网盘

另注:更简洁好用的 TM2009 没有 wine 成功,登录时弹出错误


2014年3月25日更新:TM2009 以及 TM2013 后来均 Wine 成功了,并且在输入密码时不会崩溃。详情见此文

Category: Linux | Tags: python QQ wine 腾讯
2
27
2011
9

Wine QQ隐私保护器

鉴于QQ 4 Linux实在太不好用,有些不得不使用QQ的Linux用户使用Wine来运行QQ,我经过努力也成功了,但依旧不用,因为在去年的3Q大战中我们看到腾讯实在难以信任。想想我的ssh密钥、GPG密钥、getmail和msmtp的配置文件等等非常重要的文件QQ皆可轻易扫描并上传……

想过使用另外的低权限用户来wine QQ。然而即使这样,我自己的众多文件QQ依然可以看到,心中还是不安,而且这样作为QQ的重要功能之一——互传文件——将很不方便。于是终于有一天,我开始折腾chroot了。为了不需要总是sudo,我用C写的,可以使用Linux的suid特性,同时也练习下C编程。在man相关系统调用的时候,我还发现了unshare这个调用,竟然可以把挂载的文件系统设置成只在新的挂载命名空间(mount namespace)中可见。这样就可以把为了chroot而mount --bind的项目全部隐藏起来,免得mount输出一大堆不想看到的东西。至于umount嘛,不管了,反正只是mount --bind的。

/* ===================================================================== *
 * chrooted wine QQ
 * ===================================================================== */
#define _GNU_SOURCE
#include<unistd.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<sys/mount.h>
#include<linux/limits.h>
#include<sched.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#define ROOT "/tmp/.rwine"
#define PROGRAM "你的QQ的目录"
/* 文件共享目录;若不存在会自动创建 */
#define SHAREDIR "哪个目录作为共享?"
#define BIN "Bin/QQ.exe"
#define ROOTD(dir) ROOT dir
#define MKDIR(dir) mkdir(ROOTD(dir), 0777)
#define MOUNTBIND(dir) mountbind(dir, ROOTD(dir))
int mountbind(const char *source, const char *target);
/* --------------------------------------------------------------------- */
int main(int argc, char **argv){
  int ret;
  ret = unshare(CLONE_NEWNS);
  if(ret){
    perror("unshare");
    exit(1);
  }
  seteuid(getuid());
  ret = mkdir(ROOT, 0777);
  seteuid(0);
  if(ret && errno != EEXIST){
    perror("mkdir new root dir");
    exit(1);
  }

  seteuid(getuid());
  mkdir(SHAREDIR, 0700);
  seteuid(0);
  setgid(0);
  MKDIR("/lib");
  MKDIR("/usr");
  MKDIR("/usr/share");
  MKDIR("/usr/bin");
  MKDIR("/usr/lib");
  MKDIR("/etc");
  MKDIR("/etc/fonts");
  MKDIR("/program");
  MKDIR("/dev");
  MKDIR("/tmp");
  MKDIR("/tmp/share");
  chmod(ROOTD("/tmp"), 01777);

  ret = MOUNTBIND("/lib")
    || MOUNTBIND("/usr/share")
    || MOUNTBIND("/usr/bin")
    || MOUNTBIND("/usr/lib")
    || MOUNTBIND("/etc/fonts")
    || MOUNTBIND("/dev")
    || mountbind(PROGRAM, ROOTD("/program"))
    || mountbind(SHAREDIR, ROOTD("/tmp/share"));
  if(ret){
    perror("mount --bind");
    exit(1);
  }

  char path[PATH_MAX];
  char path2[PATH_MAX];
  char *p;
  strcpy(path, getenv("HOME"));
  strcat(path, "/.wine");
  strcpy(path2, ROOT);
  p = strtok(path, "/");
  seteuid(getuid());
  while(p){
    strcat(path2, "/");
    strcat(path2, p);
    mkdir(path2, 0777);
    p = strtok(NULL, "/");
  }
  seteuid(0);
  /* path changed by strtok */
  strcpy(path, getenv("HOME"));
  strcat(path, "/.wine");
  strcpy(path2, ROOT);
  strcat(path2, path);
  ret = mountbind(path, path2);
  if(ret){
    perror("mount --bind user's wine dir");
    exit(1);
  }
  strcpy(path, getenv("HOME"));
  strcat(path, "/.fonts");
  if(access(path, X_OK) == 0){
    strcpy(path2, ROOT);
    strcat(path2, path);
    seteuid(getuid());
    mkdir(path2, 0777);
    seteuid(0);
    ret = mountbind(path, path2);
    if(ret){
      perror("mount --bind user's font dir");
      exit(1);
    }
  }
  strcpy(path, getenv("HOME"));
  strcat(path, "/.fontconfig");
  if(access(path, X_OK) == 0){
    strcpy(path2, ROOT);
    strcat(path2, path);
    seteuid(getuid());
    mkdir(path2, 0777);
    seteuid(0);
    ret = mountbind(path, path2);
    if(ret){
      perror("mount --bind user's fontconfig dir");
      exit(1);
    }
  }

  ret = chroot(ROOT);
  if(ret){
    perror("chroot");
    exit(1);
  }
  chdir("/tmp");
  ret = setuid(getuid());
  if(ret){
    perror("setuid");
    exit(1);
  }
  execl("/usr/bin/wine", "/usr/bin/wine", "/program/"BIN, NULL);
  /* execl("/usr/bin/wine", "/usr/bin/wine", "notepad", NULL); */
  perror("execl");
  return 1;
}
int mountbind(const char *source, const char *target){
  return mount(source, target, NULL, MS_BIND | MS_NOSUID, NULL);
}
/* ===================================================================== *
 * vim modeline                                                          *
 * vim:se fdm=expr foldexpr=getline(v\:lnum)=~'^\\S.*{'?'>1'\:1:         *
 * ===================================================================== */

程序名为rwine。这里的“r”可不是rsync或者rcp中的“r”,而是“rbash”、“rzsh”、“rvim”中的“r”的意思。在代码的最开头有几个宏是用来配置路径的。suid程序嘛,像这种东西还是硬编码进去好了。因为只是自己使用,所以没有做太多的错误检查之类的,健壮性应该不怎么样。对于这个程序我只要没有安全漏洞就OK了。

另外说个小插曲。在调试这段代码的时候,我发现用户的路径总是挂载得不对,检查了好久,才注意到strtok的声明是

char *strtok(char *str, const char *delim);

第一个参数那里没有const!再仔细看看man文档,果然,它把传进去的参数给改了。

Category: Linux | Tags: C代码 linux QQ 腾讯
10
14
2010
2

QQ群邮件:美好生活路上的又一障碍

如果能够不用QQ,生活会变得美好。可现实是,我不仅不得不使用QQ,而且还得使用腾讯烂得要命的群邮件服务。

QQ邮箱又挂掉了

WebQQ不知从什么时候开始不再提示新(群)邮件了。由于我们课件什么的都只知道往群邮件里发,我只好每隔几天去查收一次,不然所谓的“超大附件”会过期的。

说起“超大附件”我觉得好笑。现在都什么年代了,我网易邮箱现在6G的存储空间,附件大小可达50M,其它邮箱附件也至少可以20M。我还以为“超大附件”有几百M呢,原来才超过5M就是“超大”了。为什么腾讯不设置成1.44M的限制呢?

看到群邮箱里有不少课件,一个个手动下吧。很快就下好了,结果双击一个PPT,却是用OpenOffice Write打开的,还是空白页面。。。。我还没弄明白出什么事了,到虚拟机的XP里用MS Office打开,结果是“无法打开xxx所代表的文件类型”(微软的用词一向很怪异,我就不追究了)。再试试那些rar文件,也出错。这才注意到文件的大小不对。

OK,算我网络不行,那重新下吧。结果回邮箱里就遇到上面截图里的情况了。。。

这不是我第一次遇到,也不是第二次。我相信也不会是最后一次

唉,难道这就是劣币驱逐良币

PS: wget rocks!

Category: 未分类 | Tags: QQ 腾讯
7
26
2010
10

旧曲赋新词:《不用QQ》

Vim Talks群的tigee lee说:每个在linux下上QQ的同学,上辈子都是折翼的。。。


那天傍晚我再次上线 忍受着唯利是图的疼讯
想起曾经走过的岁月 想起曾经热爱的你
我有我想去的地方 但是我 不能离去
只因为你依然在这里 我憎恨却无能为力
我想哭 却流不出眼泪
我相喊 却发不出声音
我愿意 抛弃我的所有
如果能 不用QQ
夕阳洒在我的脸上 风儿拔动我的心弦
我多想你离开我的身旁 没有你我有多幸福
我想哭 却流不出眼泪
我想喊 却发不出声音
我愿意 抛弃我的所有
如果能 不用QQ
我想哭 却流不出眼泪
我想喊 却发不出声音
我愿意 抛弃我的所有
如果能 不用QQ
如果能 不用QQ
如果能 不用QQ

改编自汪峰演唱的《时光倒流》,墙内的朋友可在这里试听或下载这首歌。

Category: 文学 | Tags: 音乐 linux QQ 腾讯
7
22
2010
5

GM 脚本:和WebQQ的滚动标题栏说再见

作为一名中国的Linuxer,我没能像一些幸福者那样摆脱QQ,尽管我一直在见缝插针地推广Gtalk,但收效甚微。在相当长的一段时期内,我还是不得不使用WebQQ。WebQQ有一个特点让我觉得*非常非常*烦人——在来消息后就那么一直一直一直一直地滚动标题栏,似乎有天大的事需要我立即处理否则就性命难保似的。非常非常讨厌。像Gmail或者twitter那样只是在标题栏上加个括号号个数字不行吗?。。。

我再也不要默默忍受下去了!于是,点击GreaseMonkey图标,打开Vim,开始写脚本。

脚本其实很简单,只是我今天才想到可以这样子而已。WebQQ当点击聊天对话框后标题就会变正常。于是,我用Javascript模拟点击。不好监测标题栏的改变,干脆每隔几秒去点一下算了。代码如下:

// ==UserScript==
// @name           quiet WebQQ
// @namespace      http://lilydjwg.is-programmer.com/
// @description    来消息时不要滚动标题栏
// @include        http://web.qq.com/main.shtml?*
// ==/UserScript==

window.clicker = function(){
  var evt = document.createEvent("MouseEvents");
  evt.initMouseEvent("click", true, false, window,
    0, 0, 0, 0, 0, false, false, false, false, 0, null);

  var edits = document.getElementsByClassName('editArea');
  for(var i=0, len=edits.length; i<len; i++){
    edits[i].dispatchEvent(evt);
  }
};

//最多滚动三秒好了
setInterval(window.clicker, 3000);

这里clicker函数需要作为window的一个属性,否则会在页面加载完,脚本执行过后就消失了。


点击此处安装

6
30
2010
1

GM 脚本:转换QQ空间的Javascript链接为普通链接

为什么要访问难用的QQ空间我就不说了,相信各Linuxer能够理解。那为什么要把Javascript链接转换成普通链接呢?因为我喜欢用中键去点链接,让它在新标签页中打开,并且还是在后台打开。这样,在列表页面,我可以用鼠标中键选取自己感兴趣的链接,全部打开,选完好基本上第一篇也就加载好了,不需要等待加载。

无奈QQ空间特别喜欢使用Javascript,以至于我以为QQ空间里的文章都没有可以指向它的URL。后来看到QQ空间支持RSS了,才发现原来每篇文章都是有ID的,像这样可以访问:http://QQ号.qzone.qq.com/blog/文章ID。于是,此问题有解!

Firebug查看下就可以知道文章ID如何获取,然后利用强大的GreaseMonkey写个脚本转换之。思路很简单,但做起来还是遇到了点小问题——貌似在页面加载完毕之前脚本就已经执行过了。怎么办呢?我首先想到了延时,但觉得不太好控制。无意中在GreaseMonkey的右键菜单项中看到了“用户脚本命令”一项,遂Google之,获得此文。于是就用这个了,虽说每次要先去点下这个菜单项有点麻烦,但毕竟我QQ空间看得不是很多,而且这比之前要省事不少。好了,贴代码:

// ==UserScript==
// @name           QQ空间链接转换
// @namespace      http://lilydjwg.is-programmer.com/
// @description    将QQ空间链接从Javascript转换到普通链接
// @include        http://*.qzone.qq.com/*
// ==/UserScript==

var changeLinks = function(links){
  for(var i=0, len = links.length; i<len; i++){
    var link = links[i];
    if(link.href == 'javascript:;'){
      var id = link.getAttribute('onclick').match(/\d+/)[0];
      link.href = 'http://' + window.location.host + '/blog/' + id;
      console.log(link.href);
    }
  }
}

var do_it = function(){
  try{
    var links = document.getElementById('tblog').contentDocument.getElementsByClassName('blog_link');
    changeLinks(links);
    var links = document.getElementsByClassName('tx_fix');
    changeLinks(links);
  }catch(e){
    GM_log(e);
  }
}

GM_registerMenuCommand("转换js链接", do_it, '', '', 'j');

点击此处安装

| Theme: Aeros 2.0 by TheBuckmaker.com