Giter VIP home page Giter VIP logo

oicq's Introduction

oicq

npm version dm node engine discord

  • QQ(安卓)协议基于Node.js的实现,支持最低node版本为 v14
  • 若你不熟悉Node.js或不会组织代码,可通过 template 创建一个简单的应用程序
  • API Reference / Type Docs (文档仅供参考,具体类型以包内d.ts声明文件为准)
  • 从v1.x升级 (v1在master分支)
  • QQ频道未来不会直接支持,请使用插件 oicq-guild

Install:

> npm i oicq  # or > yarn add oicq

Usage:

const { createClient } = require("oicq")
const account = 147258369
const client = createClient(account)

client.on("system.online", () => console.log("Logged in!"))
client.on("message", e => {
  console.log(e)
  e.reply("hello world", true) //true表示引用对方的消息
})

client.on("system.login.qrcode", function (e) {
  //扫码后按回车登录
  process.stdin.once("data", () => {
    this.login()
  })
}).login()

注意:扫码登录现在仅能在同一ip下进行,建议使用密码登录,只需验证一次设备便长期有效
密码登录教程

Api Reference

Class: Client

使用 createClient() 或 new Client 创建实例

Method Description
login() 登录
logout() 登出
queryQrcodeResult() 获取扫码结果
submitSlider() 提交滑动验证码
sendSmsCode() 发短信
submitSmsCode() 提交短信验证码
pickGroup() 得到一个群对象
pickFriend() 得到一个好友对象
pickMember() 得到一个群员对象
pickUser() 得到一个用户对象
pickDiscuss() 得到一个讨论组对象
setOnlineStatus() 设置在线状态
setNickname() 设置昵称
setGender() 设置性别
setBirthday() 设置生日
setDescription() 设置个人说明
setSignature() 设置个性签名
setAvatar() 设置头像
getRoamingStamp() 获取漫游表情
deleteStamp() 删除漫游表情
addClass() 添加好友分组
deleteClass() 删除好友分组
renameClass() 重命名好友分组
reloadFriendList() 重载好友列表
reloadStrangerList() 重载陌生人列表
reloadGroupList() 重载群列表
reloadBlackList() 重载黑名单列表
getSystemMsg() 获取系统消息
getForwardMsg() 解析合并转发
makeForwardMsg() 制作合并转发
getVideoUrl() 获取视频地址
imageOcr() ocr
cleanCache() 清空缓存文件
Property Description
uin 我的账号
status 在线状态
nickname 昵称
sex 性别
age 年龄
fl 好友列表(Map)
gl 群列表(Map)
sl 陌生人列表(Map)
gml 群员列表缓存(Map)
blacklist 黑名单列表(Set)
classes 好友分组(Map)
stamp 漫游表情(Set))
logger 日志记录器
config 配置
dir 本地存储路径
stat 数据统计
bkn csrf-token
cookies cookies
tiny_id 我的频道账号

Events

Event Description
system.login.qrcode 收到二维码
system.login.slider 滑动验证码
system.login.device 设备锁
system.login.error 登录错误
system.online 上线
system.offline.kickoff 服务器踢下线
system.offline.network 网络错误导致下线
request.friend 好友申请
request.group.add 加群申请
request.group.invite 群邀请
request 全部请求
message.group 群消息
message.private 私聊消息
message.discuss 讨论组消息
message 全部消息
notice.friend.increase 好友增加
notice.friend.decrease 好友减少
notice.friend.recall 好友撤回
notice.friend.poke 好友戳一戳
notice.friend 好友通知
notice.group.increase 群员增加
notice.group.decrease 群员减少
notice.group.recall 群撤回
notice.group.poke 群戳一戳
notice.group.ban 群禁言
notice.group.admin 群管理变更
notice.group.transfer 群转让
notice.group 群通知
notice 全部通知
sync.message 私聊消息同步
sync.read 已读同步
guild.message 频道消息

Class: Group

群。 notice.groupmessage.group 相关事件中含有此实例 ( e.group 访问)
或者使用 client.pickGroup() 获得群实例

Method Description
sendMsg() 发送消息
recallMsg() 撤回消息
setName() 设置群名
setAvatar() 设置群头像
muteAll() 禁言全员
muteMember() 禁言群员
muteAnony() 禁言匿名者
kickMember() 踢人
pokeMember() 戳一戳
setCard() 设置名片
setAdmin() 设置管理员
setTitle() 设置头衔
invite() 邀请好友
quit() 退群/解散
getAnonyInfo() 获取匿名身份
allowAnony() 允许/禁止匿名
getChatHistory() 获取聊天记录
markRead() 标记已读
getFileUrl() 获取群文件下载地址
shareMusic() 分享音乐
getMemberMap() 获取群员列表
getAvatarUrl() 获取群头像地址
pickMember() 获取一个群成员对象
getAtAllRemainder() 获取@全体剩余次数
renew() 刷新群资料
Property Description
group_id 群号
name 群名
info 群资料
is_owner 我是否群主
is_admin 我是否管理
all_muted 是否全员禁言
mute_left 我的禁言剩余时间
fs 群文件系统

Class: User

Method Description
sendMsg() 发送消息
recallMsg() 撤回消息
getSimpleInfo() 查询资料
getChatHistory() 获取聊天记录
markRead() 标记已读
getFileUrl() 获取离线文件下载地址
getAvatarUrl() 获取头像地址
asFriend() 获取作为好友的对象
asMember() 获取作为某群群员的对象
addFriendBack() 回添双向好友
setFriendReq() 同意好友申请
setGroupReq() 同意加群申请
setGroupInvite() 同意群邀请
Property Description
user_id QQ号

Class: Friend

好友。继承 User 的所有方法和属性
notice.friendmessage.private 相关事件中含有此实例 ( e.friend 访问)
或者使用 client.pickFriend() 获得好友实例

Method Description
shareMusic() 分享音乐
setRemark() 设置备注
setClass() 设置分组
thumbUp() 点赞
poke() 戳一戳
delete() 删除
sendFile() 发送文件
forwardFile() 转发文件
recallFile() 撤回文件
Property Description
nickname 昵称
sex 性别
remark 备注
class_id 分组id
class_name 分组名
info 好友资料

Class: Member

群成员。继承 User 的所有方法和属性
message.group 相关事件中含有此实例 ( e.member 访问)
或者使用 client.pickMember() 获得群成员实例

Method Description
setAdmin() 设置管理
setTitle() 设置头衔
setCard() 设置名片
kick() 踢群
mute() 禁言
poke() 戳一戳
addFriend() 加为好友
renew() 更新群员资料
Property Description
group_id 群号
card 名片或昵称
title 头衔
is_friend 是否好友
is_owner 是否群主
is_admin 是否管理
mute_left 禁言剩余时间
group 所在群对象
info 群员资料

Class: Contactable

抽象类,用户和群的基类,里面的方法和属性都会被继承

Method Description
uploadImages() 上传一批图片以备发送
uploadVideo() 上传一个视频以备发送
uploadPtt() 上传一个语音以备发送
makeForwardMsg() 制作合并转发消息以备发送
getForwardMsg() 解析合并转发消息
getVideoUrl() 获取视频下载地址
Property Description
client 所在客户端对象

Class: Gfs

群文件系统,通过 group.fs 获取

Method Description
df() 查询使用空间
stat() 获取文件或目录属性
dir() 列出文件和目录
ls() dir的别名
mkdir() 创建目录
rm() 删除文件或目录
rename() 重命名文件或目录
mv() 移动文件
upload() 上传文件
forward() 转发文件
download() 获取下载链接
Property Description
group_id 群号
group 所在群对象
client 所在客户端对象

Class: Message

拥有子类: PrivateMessage, GroupMessage, DiscussMessage
对应的消息事件中含有这些实例中的一个

Method Description
serialize() 序列化一条消息
toString() 一种适合阅读的形式
Static Method Description
deserialize() 反序列化一条消息
Property Description
message_type 消息类别:群或私聊
sub_type 子类别
group_id 群号
from_id 发送者
to_id 接收者
anonymous 匿名者信息
auto_reply 是否自动回复
block 是否屏蔽
atme 是否atme
atall 是否atall
message 消息链
raw_message 消息摘要
sender 发送者
time 消息时间
seq 消息序号
rand 消息随机数
font 字体
source 引用回复的消息

Namespace: segment

用于创建可发送的消息元素类型

//样例代码,文字+图片+表情+AT
const { segment } = require("oicq")
const message = [
  "hello world",
  segment.image("/tmp/abc.jpg"),
  segment.face(104),
  segment.at(10001),
]
Method Description
at() 创建at元素
face() 创建表情元素
image() 创建图片元素
flash() 创建闪照元素
video() 创建视频元素
record() 创建语音元素
xml() 创建xml元素
json() 创建json元素
share() 创建链接分享元素
location() 创建地点分享元素
poke() 创建戳一戳元素
bface() 创建bface元素
sface() 创建sface元素
mirai() 创建特殊元素

其他:

group:236172566

oicq's People

Contributors

14kay avatar 885228438 avatar clansty avatar cloud370 avatar dawnnights avatar dmlgzs avatar goodspeed34 avatar juergenie avatar lc-cn avatar ltxhhz avatar lz1998 avatar magren0321 avatar nk-ava avatar nonusx avatar steve-xmh avatar takayama-lily avatar thesnowfield avatar timerainstarsky avatar yanyunwu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

oicq's Issues

bot.login出错

TypeError [ERR_INVALID_ARG_TYPE]: The "chunk" argument must be one of type string, Buffer, or Uint8Array. Received type number
    at chunkInvalid (_stream_readable.js:329:12)
    at readableAddChunk (_stream_readable.js:261:12)
    at Readable.push (_stream_readable.js:224:10)
    at next (internal/streams/from.js:34:27)
    at processTicksAndRejections (internal/process/task_queues.js:94:5)

协议部分

我对协议实现部分比较感兴趣,可以沟通交流下吗

[温馨提示]当前版本过低,请先升级到手机QQ最新版本。

使用的是demo代码
node index.js
OICQ程序启动。当前内核版本:v1.10.3
[2020-11-08T23:32:53.171] [INFO] [BOT:xxxxx] - connecting to msfwifi.3g.qq.com:8080
[2020-11-08T23:32:53.219] [INFO] [BOT:xxxxx] - 61.181.203.13:8080 connected
[2020-11-08T23:32:53.503] [ERROR] [BOT:xxxxx] - [温馨提示]当前版本过低,请先升级到手机QQ最新版本。

TypeError: Cannot read property 'readInt32BE' of null

TypeError: Cannot read property 'readInt32BE' of null

// lib/core.js
function parseIncomingPacket(packet) {
  const stream = Readable.from(packet, { objectMode: false });
  console.log(packet);
  console.log(stream.read(4)); // null
  const flag1 = stream.read(4).readInt32BE();
}

Escaping `+` in base64 encoded images

接收到的

[CQ:image,file=base64:///9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAAeAB4DASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD3+iiigAooooAKzdf1m38PeH7/AFe6/wBVaQNKRnG4gcKPcnA/GtKuG8c/8TfxH4W8LPxa3t095dZ6SR24DiPHoWK5+lAD9K1j/hDfANhe+Kr65m1C6YO6HdLK88pLCGNeTxnaFHA21taB4jbXZJ0bQtZ0zyQrA6jbrGJM5+7hjkjHI4xkVy3xDnXTvG/gHU518y2j1Ca2aIdS8sYVG9PlIJrvvtSfbWtQreYsYkJ7YJI/PigD/9k=]

会变成

获取本地图片 base64:///9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAAeAB4DASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4 Tl5ufo6erx8vP09fb3 Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3 Pn6/9oADAMBAAIRAxEAPwD3 iiigAooooAKzdf1m38PeH7/AFe6/wBVaQNKRnG4gcKPcnA/GtKuG8c/8TfxH4W8LPxa3t095dZ6SR24DiPHoWK5 lAD9K1j/hDfANhe Kr65m1C6YO6HdLK88pLCGNeTxnaFHA21taB4jbXZJ0bQtZ0zyQrA6jbrGJM5 7hjkjHI4xkVy3xDnXTvG/gHU518y2j1Ca2aIdS8sYVG9PlIJrvvtSfbWtQreYsYkJ7YJI/PigD/9k= 失败,已忽略该图片。

简单看了下似乎是将+转义成了空格导致base64的内容出了问题。

系统时间不正常导致私聊信息收不到

a

在core.js文件 里 this.msgExists() 这个函数一直continue。 是timestamp() - time >= 60了。是本地时间被我改了。 这里遇到了坑。
建议取消这个限制? 或者优化下?

无法发送本地文件语音

如题,尝试自己看了一下问题好像出现在 lib/message/builder.js 里面:

async function audioTrans(cache_filepath, file) {
    let filepath, tmp;
    if (typeof file === "string") {
        filepath = file;
        file = await readFile(filepath, 0xfffffff); // 这里
    } else {
        tmp = Math.random() + "" + Date.now();
// ...

改成这样之后就可以上传发送了:

async function audioTrans(cache_filepath, file) {
    let filepath, tmp;
    if (typeof file === "string") {
        filepath = file;
        file = await fs.promises.readFile(filepath); // 这里
    } else {
        tmp = Math.random() + "" + Date.now();
// ...

但是不知道会不会有什么影响,还请大佬检查一下代码吧。

能否增加mac协议?

go-cqhttp已经有mac协议支持了,可能比pad,安卓更加完美,能否把设备信息做成配置文件,也方便修改

禁止登陆

[禁止登录]当前上网环境异常,请更换网络环境或在常用设备上登录或稍后再
试 QQ是可以正常登陆的,换个账号也不行

QQ机器人的QQ版本是不是太低了

场景:有时需要转发别人发的视频和图片消息
发现有部分消息显示[视频]你的QQ暂不支持查看视频短片,请升级到最新版本后查看。

如何获取好友生日

好友列表里只有age信息,而且都是0
qq现在送好友生日礼物不是收费的就是要看广告。
希望加个getUserInfo(uin) 的接口

一些问题(备忘录)

  • 将network层分离出去
  • 升级jce
  • 重写tea
  • 读取本地图片文件使用stream并限制大小
  • 发消息的逻辑不易理解,写一个单独类
  • face和sface合并
  • 重新设计message_id并实现reply
  • exchange_emp
  • 缓存匿名id
  • 提供刷新好友、群、群员列表
  • 心跳稳定性
  • 记录图片的长宽参数
  • 发图支持headers
  • 收发消息的逻辑还需优化
  • 部分账号加载群列表异常
  • 部分账号emp失败
  • 群列表偶尔加载不完整(Simple?)
  • 带特殊字符的群名片
  • 多字符emoji在切片中心时会乱码
  • MacOS和iPad协议掉线问题
  • xml的svcid问题
  • 私聊消息出现转发为空
  • 分片消息偶尔丢失最后一个分片

getLoginInfo()永远返回data: {user_id: XXXXXX, nickname: "", age: 0, sex: "unknown"}

作者您好,感谢您做了如此实用简单的bot,这对一个弱类型语言的开发者来说简直就是福音。我使用您的代码结合做一个客户端程序时候,发现登录成功后找不到合适的方法来判断登录的状态?为什么通过getLoginInfo()拿不到正确的登录信息,但实列化client对象属性中的登录状态又是正确的呢?

戳一戳接受不到

notice.friend.poke 好友测试没效果
群聊测试戳一戳也没效果

const { createClient } = require("oicq");
const uin = ; // your account
const bot = createClient(uin);
const password = "";  // your password or password_md5
bot.login(password);
bot.on("system.login.captcha", () => {
    process.stdin.once("data", input => {
        bot.captchaLogin(input);
    });
});

bot.on("message", data => {
    console.log(data);
    if (data.group_id > 0)
        bot.sendGroupMsg(data.group_id, "hello");
    else
        bot.sendPrivateMsg(data.user_id, "hello");
});
bot.on("notice", data => {
    console.log(data);
});

更改protobuf的实现方式

不再使用传统.proto定义字段的方式。
改为使用pb手动组包/解包的方式。
(可能需要换掉protobufjs)

热重载

不知道有没有热重载这个功能 希望以后能添加

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.