openwechat

package module
v0.0.0-...-5259114 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 25, 2021 License: Apache-2.0 Imports: 23 Imported by: 0

README

openwechat

Go Doc

golang版个人微信号API, 突破网页版限制,类似开发公众号一样,开发个人微信号

微信机器人😈,利用微信号完成一些功能的定制化开发⭐

  • 支持定制化开发,如日志记录,自动回复
  • 突破网页版登录限制📣
  • 无需重复扫码登录
  • 支持多个微信号同时登陆
安装

go get

go get github.com/eatMoreApple/openwechat
快速开始
package main

import (
	"fmt"
	"github.com/eatMoreApple/openwechat"
)

func main() {
	bot := openwechat.DefaultBot()
  // bot := openwechat.DefaultBot(openwechat.Desktop) // 桌面模式,上面登录不上的可以尝试切换这种模式

	// 注册消息处理函数
	bot.MessageHandler = func(msg *openwechat.Message) {
		if msg.IsText() && msg.Content == "ping" {
			msg.ReplyText("pong")
		}
	}
	// 注册登陆二维码回调
	bot.UUIDCallback = openwechat.PrintlnQrcodeUrl

	// 登陆
	if err := bot.Login(); err != nil {
		fmt.Println(err)
		return
	}

	// 获取登陆的用户
	self, err := bot.GetCurrentUser()
	if err != nil {
		fmt.Println(err)
		return
	}

	// 获取所有的好友
	friends, err := self.Friends()
	fmt.Println(friends, err)

	// 获取所有的群组
	groups, err := self.Groups()
	fmt.Println(groups, err)

	// 阻塞主goroutine, 知道发生异常或者用户主动退出
	bot.Block()
}
支持功能
  • 消息回复、给指定对象(好友、群组)发送文本、图片、文件、emoji表情等消息
  • 热登陆(无需重复扫码登录)、自定义消息处理、文件下载、消息防撤回
  • 获取对象信息、设置好友备注、拉好友进群等
  • 更多功能请查看文档
文档

点击查看

项目主页

https://github.com/eatMoreApple/openwechat

Thanks

JetBrains

Documentation

Index

Constants

View Source
const (
	TextMessage  = 1
	ImageMessage = 3
	AppMessage   = 6
)

消息类型

View Source
const (
	MsgtypeText              = 1     // 文本消息
	MsgtypeImage             = 3     // 图片消息
	MsgtypeVoice             = 34    // 语音消息
	MsgtypeVerifymsg         = 37    // 认证消息
	MsgtypePossiblefriendMsg = 40    // 好友推荐消息
	MsgtypeSharecard         = 42    // 名片消息
	MsgtypeVideo             = 43    // 视频消息
	MsgtypeEmoticon          = 47    // 表情消息
	MsgtypeLocation          = 48    // 地理位置消息
	MsgtypeApp               = 49    // APP消息
	MsgtypeVoipmsg           = 50    // voip msg	//VOIP消息
	MsgtypeVoipnotify        = 52    // voip 结束消息
	MsgtypeVoipinvite        = 53    // voip 邀请
	MsgtypeMicrovideo        = 62    // 小视频消息
	MsgtypeSys               = 10000 // 系统消息
	MsgtypeRecalled          = 10002 // 消息撤回
)

https://res.wx.qq.com/a/wx_fed/webwx/res/static/js/index_c7d281c.js

varcaser.Caser{
		From: varcaser.ScreamingSnakeCase, To: varcaser.UpperCamelCaseKeepCaps}
View Source
const (
	MALE   = 1
	FEMALE = 2
)

性别

View Source
const (
	Normal  mode = "normal"
	Desktop mode = "desktop" // 突破网页版登录限制
)

向外暴露2种模式

View Source
const ALL = 0

ALL跟search函数搭配

friends.Search(openwechat.ALL, )
View Source
const TimeFormat = "Mon Jan 02 2006 15:04:05 GMT+0800 (中国标准时间)"
View Source
const ZombieText = "وُحfخe ̷̴̐nخg ̷̴̐cخh ̷̴̐aخo امارتيخ ̷̴̐خ\n"

ZombieText 检测僵尸好友字符串 发送该字符给好友,能正常发送不报错的为正常好友,否则为僵尸好友

Variables

View Source
var Emoji = struct {
	Smile        string
	Grimace      string
	Drool        string
	Scowl        string
	CoolGuy      string
	Sob          string
	Shy          string
	Silent       string
	Sleep        string
	Cry          string
	Awkward      string
	Angry        string
	Tongue       string
	Grin         string
	Surprise     string
	Frown        string
	Ruthless     string
	Blush        string
	Scream       string
	Puke         string
	Chuckle      string
	Joyful       string
	Slight       string
	Smug         string
	Hungry       string
	Drowsy       string
	Panic        string
	Sweat        string
	Laugh        string
	Commando     string
	Determined   string
	Scold        string
	Shocked      string
	Shhh         string
	Dizzy        string
	Tormented    string
	Toasted      string
	Skull        string
	Hammer       string
	Wave         string
	Speechless   string
	NosePick     string
	Clap         string
	Shame        string
	Trick        string
	BahL         string
	BahR         string
	Yawn         string
	PoohPooh     string
	Shrunken     string
	TearingUp    string
	Sly          string
	Kiss         string
	Wrath        string
	Whimper      string
	Cleaver      string
	Watermelon   string
	Beer         string
	Basketball   string
	PingPong     string
	Coffee       string
	Rice         string
	Pig          string
	Rose         string
	Wilt         string
	Lips         string
	Heart        string
	BrokenHeart  string
	Cake         string
	Lightning    string
	Bomb         string
	Dagger       string
	Soccer       string
	Ladybug      string
	Poop         string
	Moon         string
	Sun          string
	Gift         string
	Hug          string
	ThumbsUp     string
	ThumbsDown   string
	Shake        string
	Peace        string
	Fight        string
	Beckon       string
	Fist         string
	Pinky        string
	RockOn       string
	Nuhuh        string
	OK           string
	InLove       string
	Blowkiss     string
	Waddle       string
	Tremble      string
	Aaagh        string
	Twirl        string
	Kotow        string
	Dramatic     string
	JumpRope     string
	Surrender    string
	Hooray       string
	Meditate     string
	Smooch       string
	TaiChiL      string
	TaiChiR      string
	Hey          string
	Facepalm     string
	Smirk        string
	Smart        string
	Moue         string
	Yeah         string
	Tea          string
	Packet       string
	Candle       string
	Blessing     string
	Chick        string
	Onlooker     string
	GoForIt      string
	Sweats       string
	OMG          string
	Emm          string
	Respect      string
	Doge         string
	NoProb       string
	MyBad        string
	KeepFighting string
	Wow          string
	Rich         string
	Broken       string
	Hurt         string
	Sigh         string
	LetMeSee     string
	Awesome      string
	Boring       string

}{}/* 134 elements not displayed */

emoji 表情 字段太多了,污染命名空间,封装成struct返回

Functions

func DispatchMessage

func DispatchMessage(dispatcher MessageDispatcher) func(msg *Message)

跟 MessageDispatcher 结合封装成 MessageHandler

func FormatEmoji

func FormatEmoji(text string) string

func GetFileContentType

func GetFileContentType(file multipart.File) (string, error)

获取文件上传的类型

func GetQrcodeUrl

func GetQrcodeUrl(uuid string) string

通过uuid获取登录二维码的url

func GetRandomDeviceId

func GetRandomDeviceId() string

获取随机设备id

func NewFileAppMessage

func NewFileAppMessage(stat os.FileInfo, attachId string) *appmsg

func PrintlnQrcodeUrl

func PrintlnQrcodeUrl(uuid string)

打印登录二维码

func ToBuffer

func ToBuffer(v interface{}) (*bytes.Buffer, error)

func XmlFormString

func XmlFormString(text string) string

Form Xml 格式化

Types

type BaseRequest

type BaseRequest struct {
	Uin                 int
	Sid, Skey, DeviceID string
}

初始的请求信息 几乎所有的请求都要携带该参数

type BaseResponse

type BaseResponse struct {
	Ret    int
	ErrMsg string
}

大部分返回对象都携带该信息

func (BaseResponse) Error

func (b BaseResponse) Error() string

func (BaseResponse) Ok

func (b BaseResponse) Ok() bool

type Bot

type Bot struct {
	ScanCallBack           func(body []byte) // 扫码回调,可获取扫码用户的头像
	LoginCallBack          func(body []byte) // 登陆回调
	LogoutCallBack         func(bot *Bot)    // 退出回调
	UUIDCallback           func(uuid string) // 获取UUID的回调函数
	MessageHandler         MessageHandler    // 获取消息成功的handle
	GetMessageErrorHandler func(err error)   // 获取消息发生错误的handle

	Caller *Caller
	// contains filtered or unexported fields
}

func DefaultBot

func DefaultBot(modes ...mode) *Bot

默认的Bot的构造方法, mode不传入默认为openwechat.Normal,详情见mode

bot := openwechat.DefaultBot(openwechat.Desktop)

func NewBot

func NewBot(caller *Caller) *Bot

Bot的构造方法,需要自己传入Caller

func (*Bot) Alive

func (b *Bot) Alive() bool

判断当前用户是否正常在线

func (*Bot) Block

func (b *Bot) Block() error

当消息同步发生了错误或者用户主动在手机上退出,该方法会立即返回,否则会一直阻塞

func (*Bot) CrashReason

func (b *Bot) CrashReason() error

获取当前Bot崩溃的原因

func (*Bot) DumpHotReloadStorage

func (b *Bot) DumpHotReloadStorage() error

写入HotReloadStorage

func (*Bot) GetCurrentUser

func (b *Bot) GetCurrentUser() (*Self, error)

获取当前的用户

self, err := bot.GetCurrentUser()
if err != nil {
	return
}
fmt.Println(self.NickName)

func (*Bot) HotLogin

func (b *Bot) HotLogin(storage HotReloadStorage, retry ...bool) error

热登录,可实现重复登录, retry设置为true可在热登录失效后进行普通登录行为

storage := NewJsonFileHotReloadStorage("storage.json")
err := bot.HotLogin(storage, true)
fmt.Println(err)

func (*Bot) Login

func (b *Bot) Login() error

用户登录 该方法会一直阻塞,直到用户扫码登录,或者二维码过期

func (*Bot) Logout

func (b *Bot) Logout() error

用户退出

func (*Bot) MessageOnError

func (b *Bot) MessageOnError(h func(err error))

setter for Bot.GetMessageErrorHandler

func (*Bot) MessageOnSuccess

func (b *Bot) MessageOnSuccess(h func(msg *Message))

setter for Bot.MessageHandler

type Caller

type Caller struct {
	Client *Client
	// contains filtered or unexported fields
}

调用请求和解析请求 上层模块可以直接获取封装后的请求结果

func DefaultCaller

func DefaultCaller() *Caller

Default Constructor for Caller

func NewCaller

func NewCaller(client *Client) *Caller

Constructor for Caller

func (*Caller) AddFriendIntoChatRoom

func (c *Caller) AddFriendIntoChatRoom(req *BaseRequest, info *LoginInfo, group *Group, friends ...*Friend) error

拉好友入群

func (*Caller) CheckLogin

func (c *Caller) CheckLogin(uuid string) (*CheckLoginResponse, error)

检查是否登录成功

func (*Caller) GetLoginInfo

func (c *Caller) GetLoginInfo(body []byte) (*LoginInfo, error)

获取登录信息

func (*Caller) GetLoginUUID

func (c *Caller) GetLoginUUID() (string, error)

获取登录的uuid

func (*Caller) Logout

func (c *Caller) Logout(info *LoginInfo) error

用户退出

func (*Caller) RemoveFriendFromChatRoom

func (c *Caller) RemoveFriendFromChatRoom(req *BaseRequest, info *LoginInfo, group *Group, users ...*User) error

从群聊中移除用户

func (*Caller) SyncCheck

func (c *Caller) SyncCheck(info *LoginInfo, response *WebInitResponse) (*SyncCheckResponse, error)

异步获取是否有新的消息

func (*Caller) UploadMedia

func (c *Caller) UploadMedia(file *os.File, request *BaseRequest, info *LoginInfo, fromUserName, toUserName string) (*UploadResponse, error)

func (*Caller) WebInit

func (c *Caller) WebInit(request *BaseRequest) (*WebInitResponse, error)

获取初始化信息

func (*Caller) WebWxBatchGetContact

func (c *Caller) WebWxBatchGetContact(members Members, request *BaseRequest) (Members, error)

获取联系人的详情 注: Members参数的长度不要大于50

func (*Caller) WebWxGetContact

func (c *Caller) WebWxGetContact(info *LoginInfo) (Members, error)

获取所有的联系人

func (*Caller) WebWxOplog

func (c *Caller) WebWxOplog(request *BaseRequest, remarkName, toUserName string) error

修改用户备注接口

func (*Caller) WebWxRevokeMsg

func (c *Caller) WebWxRevokeMsg(msg *SentMessage, request *BaseRequest) error

撤回消息操作

func (*Caller) WebWxSendAppMsg

func (c *Caller) WebWxSendAppMsg(msg *SendMessage, req *BaseRequest) (*SentMessage, error)

发送媒体消息

func (*Caller) WebWxSendFile

func (c *Caller) WebWxSendFile(file *os.File, req *BaseRequest, info *LoginInfo, fromUserName, toUserName string) (*SentMessage, error)

func (*Caller) WebWxSendImageMsg

func (c *Caller) WebWxSendImageMsg(file *os.File, request *BaseRequest, info *LoginInfo, fromUserName, toUserName string) (*SentMessage, error)

发送图片消息接口

func (*Caller) WebWxSendMsg

func (c *Caller) WebWxSendMsg(msg *SendMessage, info *LoginInfo, request *BaseRequest) (*SentMessage, error)

发送消息接口

func (*Caller) WebWxStatusNotify

func (c *Caller) WebWxStatusNotify(request *BaseRequest, response *WebInitResponse, info *LoginInfo) error

通知手机已登录

func (*Caller) WebWxSync

func (c *Caller) WebWxSync(request *BaseRequest, response *WebInitResponse, info *LoginInfo) (*WebWxSyncResponse, error)

获取新的消息接口

func (*Caller) WebWxVerifyUser

func (c *Caller) WebWxVerifyUser(storage *Storage, info RecommendInfo, verifyContent string) error

同意加好友请求

type Card

type Card struct {
	XMLName                 xml.Name `xml:"msg"`
	ImageStatus             int      `xml:"imagestatus,attr"`
	Scene                   int      `xml:"scene,attr"`
	Sex                     int      `xml:"sex,attr"`
	Certflag                int      `xml:"certflag,attr"`
	BigHeadImgUrl           string   `xml:"bigheadimgurl,attr"`
	SmallHeadImgUrl         string   `xml:"smallheadimgurl,attr"`
	UserName                string   `xml:"username,attr"`
	NickName                string   `xml:"nickname,attr"`
	ShortPy                 string   `xml:"shortpy,attr"`
	Alias                   string   `xml:"alias,attr"` // Note: 这个是名片用户的微信号
	Province                string   `xml:"province,attr"`
	City                    string   `xml:"city,attr"`
	Sign                    string   `xml:"sign,attr"`
	Certinfo                string   `xml:"certinfo,attr"`
	BrandIconUrl            string   `xml:"brandIconUrl,attr"`
	BrandHomeUr             string   `xml:"brandHomeUr,attr"`
	BrandSubscriptConfigUrl string   `xml:"brandSubscriptConfigUrl,attr"`
	BrandFlags              string   `xml:"brandFlags,attr"`
	RegionCode              string   `xml:"regionCode,attr"`
}

名片消息内容

type CheckLoginResponse

type CheckLoginResponse struct {
	Code string
	Raw  []byte
}

type Client

type Client struct {
	HttpHooks HttpHooks
	*http.Client
	// contains filtered or unexported fields
}

http请求客户端 客户端需要维持Session会话 并且客户端不允许跳转

func DefaultClient

func DefaultClient() *Client

自动存储cookie 设置客户端不自动跳转

func NewClient

func NewClient(client *http.Client) *Client

func (*Client) AddHttpHook

func (c *Client) AddHttpHook(hooks ...HttpHook)

func (*Client) AddMemberIntoChatRoom

func (c *Client) AddMemberIntoChatRoom(req *BaseRequest, info *LoginInfo, group *Group, friends ...*Friend) (*http.Response, error)

添加用户进群聊

func (*Client) CheckLogin

func (c *Client) CheckLogin(uuid string) (*http.Response, error)

检查是否登录

func (*Client) Do

func (c *Client) Do(req *http.Request) (*http.Response, error)

抽象Do方法,将所有的有效的cookie存入Client.cookies 方便热登陆时获取

func (*Client) GetCookieMap

func (c *Client) GetCookieMap() map[string][]*http.Cookie

获取当前client的所有的有效的client

func (*Client) GetLoginInfo

func (c *Client) GetLoginInfo(path string) (*http.Response, error)

GetLoginInfo 请求获取LoginInfo

func (*Client) GetLoginQrcode

func (c *Client) GetLoginQrcode(uuid string) (*http.Response, error)

获取登录的二维吗

func (*Client) GetLoginUUID

func (c *Client) GetLoginUUID() (*http.Response, error)

获取登录的uuid

func (*Client) Logout

func (c *Client) Logout(info *LoginInfo) (*http.Response, error)

用户退出

func (*Client) RemoveMemberFromChatRoom

func (c *Client) RemoveMemberFromChatRoom(req *BaseRequest, info *LoginInfo, group *Group, friends ...*User) (*http.Response, error)

从群聊中移除用户

func (*Client) SyncCheck

func (c *Client) SyncCheck(info *LoginInfo, response *WebInitResponse) (*http.Response, error)

异步检查是否有新的消息返回

func (*Client) WebInit

func (c *Client) WebInit(request *BaseRequest) (*http.Response, error)

请求获取初始化信息

func (*Client) WebWxBatchGetContact

func (c *Client) WebWxBatchGetContact(members Members, request *BaseRequest) (*http.Response, error)

获取联系人详情

func (*Client) WebWxGetContact

func (c *Client) WebWxGetContact(info *LoginInfo) (*http.Response, error)

获取联系人信息

func (*Client) WebWxGetHeadImg

func (c *Client) WebWxGetHeadImg(headImageUrl string) (*http.Response, error)

获取用户的头像

func (*Client) WebWxGetMedia

func (c *Client) WebWxGetMedia(msg *Message, info *LoginInfo) (*http.Response, error)

获取文件消息的文件响应

func (*Client) WebWxGetMsgImg

func (c *Client) WebWxGetMsgImg(msg *Message, info *LoginInfo) (*http.Response, error)

获取图片消息的图片响应

func (*Client) WebWxGetVideo

func (c *Client) WebWxGetVideo(msg *Message, info *LoginInfo) (*http.Response, error)

获取视频消息的视频响应

func (*Client) WebWxGetVoice

func (c *Client) WebWxGetVoice(msg *Message, info *LoginInfo) (*http.Response, error)

获取语音消息的语音响应

func (*Client) WebWxOplog

func (c *Client) WebWxOplog(request *BaseRequest, remarkName, userName string) (*http.Response, error)

用户重命名接口

func (*Client) WebWxRevokeMsg

func (c *Client) WebWxRevokeMsg(msg *SentMessage, request *BaseRequest) (*http.Response, error)

撤回消息

func (*Client) WebWxSendAppMsg

func (c *Client) WebWxSendAppMsg(msg *SendMessage, request *BaseRequest) (*http.Response, error)

发送文件信息

func (*Client) WebWxSendMsg

func (c *Client) WebWxSendMsg(msg *SendMessage, info *LoginInfo, request *BaseRequest) (*http.Response, error)

发送文本消息

func (*Client) WebWxSendMsgImg

func (c *Client) WebWxSendMsgImg(msg *SendMessage, request *BaseRequest, info *LoginInfo) (*http.Response, error)

发送图片 这个接口依赖上传文件的接口 发送的图片必须是已经成功上传的图片

func (*Client) WebWxStatusNotify

func (c *Client) WebWxStatusNotify(request *BaseRequest, response *WebInitResponse, info *LoginInfo) (*http.Response, error)

通知手机已登录

func (*Client) WebWxSync

func (c *Client) WebWxSync(request *BaseRequest, response *WebInitResponse, info *LoginInfo) (*http.Response, error)

获取消息接口

func (*Client) WebWxUploadMediaByChunk

func (c *Client) WebWxUploadMediaByChunk(file *os.File, request *BaseRequest, info *LoginInfo, forUserName, toUserName string) (*http.Response, error)

func (*Client) WebWxVerifyUser

func (c *Client) WebWxVerifyUser(storage *Storage, info RecommendInfo, verifyContent string) (*http.Response, error)

添加用户为好友接口

type Friend

type Friend struct{ *User }

func NewFriendHelper

func NewFriendHelper(self *Self) *Friend

这里为了兼容Desktop版本找不到文件传输助手的问题 文件传输助手的微信身份标识符永远是filehelper 这种形式的对象可能缺少一些其他属性 但是不影响发送信息的功能

func (*Friend) AddIntoGroup

func (f *Friend) AddIntoGroup(groups ...*Group) error

拉该好友入群

func (*Friend) SendFile

func (f *Friend) SendFile(file *os.File) (*SentMessage, error)

发送文件消息

func (*Friend) SendImage

func (f *Friend) SendImage(file *os.File) (*SentMessage, error)

发送图片消息

func (*Friend) SendMsg

func (f *Friend) SendMsg(msg *SendMessage) (*SentMessage, error)

发送自定义消息

func (*Friend) SendText

func (f *Friend) SendText(content string) (*SentMessage, error)

发送文本消息

func (*Friend) SetRemarkName

func (f *Friend) SetRemarkName(name string) error

重命名当前好友

func (Friend) String

func (f Friend) String() string

implement fmt.Stringer

type FriendAddMessage

type FriendAddMessage struct {
	XMLName           xml.Name `xml:"msg"`
	Shortpy           int      `xml:"shortpy,attr"`
	ImageStatus       int      `xml:"imagestatus,attr"`
	Scene             int      `xml:"scene,attr"`
	PerCard           int      `xml:"percard,attr"`
	Sex               int      `xml:"sex,attr"`
	AlbumFlag         int      `xml:"albumflag,attr"`
	AlbumStyle        int      `xml:"albumstyle,attr"`
	SnsFlag           int      `xml:"snsflag,attr"`
	Opcode            int      `xml:"opcode,attr"`
	FromUserName      string   `xml:"fromusername,attr"`
	EncryptUserName   string   `xml:"encryptusername,attr"`
	FromNickName      string   `xml:"fromnickname,attr"`
	Content           string   `xml:"content,attr"`
	Country           string   `xml:"country,attr"`
	Province          string   `xml:"province,attr"`
	City              string   `xml:"city,attr"`
	Sign              string   `xml:"sign,attr"`
	Alias             string   `xml:"alias,attr"`
	WeiBo             string   `xml:"weibo,attr"`
	AlbumBgImgId      string   `xml:"albumbgimgid,attr"`
	SnsBgImgId        string   `xml:"snsbgimgid,attr"`
	SnsBgObjectId     string   `xml:"snsbgobjectid,attr"`
	MHash             string   `xml:"mhash,attr"`
	MFullHash         string   `xml:"mfullhash,attr"`
	BigHeadImgUrl     string   `xml:"bigheadimgurl,attr"`
	SmallHeadImgUrl   string   `xml:"smallheadimgurl,attr"`
	Ticket            string   `xml:"ticket,attr"`
	GoogleContact     string   `xml:"googlecontact,attr"`
	QrTicket          string   `xml:"qrticket,attr"`
	ChatRoomUserName  string   `xml:"chatroomusername,attr"`
	SourceUserName    string   `xml:"sourceusername,attr"`
	ShareCardUserName string   `xml:"sharecardusername,attr"`
	ShareCardNickName string   `xml:"sharecardnickname,attr"`
	CardVersion       string   `xml:"cardversion,attr"`
	BrandList         struct {
		Count int   `xml:"count,attr"`
		Ver   int64 `xml:"ver,attr"`
	} `xml:"brandlist"`
}

好友添加消息信息内容

type Friends

type Friends []*Friend

func (Friends) Count

func (f Friends) Count() int

获取好友的数量

func (Friends) First

func (f Friends) First() *Friend

获取第一个好友

func (Friends) Last

func (f Friends) Last() *Friend

获取最后一个好友

func (Friends) Search

func (f Friends) Search(limit int, condFuncList ...func(friend *Friend) bool) (results Friends)

根据自定义条件查找好友

func (Friends) SearchByNickName

func (f Friends) SearchByNickName(limit int, nickName string) (results Friends)

根据昵称查找好友

func (Friends) SearchByRemarkName

func (f Friends) SearchByRemarkName(limit int, remarkName string) (results Friends)

根据备注查找好友

func (Friends) SearchByUserName

func (f Friends) SearchByUserName(limit int, username string) (results Friends)

根据用户名查找好友

func (Friends) SendFile

func (f Friends) SendFile(file *os.File, delay ...time.Duration) error

群发文件

func (Friends) SendImage

func (f Friends) SendImage(file *os.File, delay ...time.Duration) error

向slice的好友依次发送图片消息

func (Friends) SendMsg

func (f Friends) SendMsg(msg *SendMessage, delay ...time.Duration) error

向slice的好友依次发送消息

func (Friends) SendText

func (f Friends) SendText(text string, delay ...time.Duration) error

向slice的好友依次发送文本消息

type Group

type Group struct{ *User }

func (*Group) AddFriendsIn

func (g *Group) AddFriendsIn(friends ...*Friend) error

拉好友入群

func (*Group) Members

func (g *Group) Members() (Members, error)

获取所有的群成员

func (*Group) RemoveMembers

func (g *Group) RemoveMembers(members Members) error

从群聊中移除用户 Deprecated 无论是网页版,还是程序上都不起作用

func (*Group) SendFile

func (g *Group) SendFile(file *os.File) (*SentMessage, error)

发送文件给当前的群组

func (*Group) SendImage

func (g *Group) SendImage(file *os.File) (*SentMessage, error)

发行图片消息给当前的群组

func (*Group) SendMsg

func (g *Group) SendMsg(msg *SendMessage) (*SentMessage, error)

发行消息给当前的群组

func (*Group) SendText

func (g *Group) SendText(content string) (*SentMessage, error)

发行文本消息给当前的群组

func (Group) String

func (g Group) String() string

implement fmt.Stringer

type Groups

type Groups []*Group

func (Groups) Count

func (g Groups) Count() int

获取群组数量

func (Groups) First

func (g Groups) First() *Group

获取第一个群组

func (Groups) Last

func (g Groups) Last() *Group

获取最后一个群组

func (Groups) Search

func (g Groups) Search(limit int, condFuncList ...func(group *Group) bool) (results Groups)

根据自定义条件查找群组

func (Groups) SearchByNickName

func (g Groups) SearchByNickName(limit int, nickName string) (results Groups)

根据昵称查找群组

func (Groups) SearchByRemarkName

func (g Groups) SearchByRemarkName(limit int, remarkName string) (results Groups)

根据备注查找群组

func (Groups) SearchByUserName

func (g Groups) SearchByUserName(limit int, username string) (results Groups)

根据用户名查找群组

func (Groups) SendImage

func (g Groups) SendImage(file *os.File, delay ...time.Duration) error

向群组依次发送图片消息, 支持发送延迟

func (Groups) SendMsg

func (g Groups) SendMsg(msg *SendMessage, delay ...time.Duration) error

向群组依次发送消息, 支持发送延迟

func (Groups) SendText

func (g Groups) SendText(text string, delay ...time.Duration) error

向群组依次发送文本消息, 支持发送延迟

type HotReloadStorage

type HotReloadStorage interface {
	GetHotReloadStorageItem() HotReloadStorageItem // 获取HotReloadStorageItem
	Dump(item HotReloadStorageItem) error          // 实现该方法, 将必要信息进行序列化
	Load() error                                   // 实现该方法, 将存储媒介的内容反序列化
}

热登陆存储接口

type HotReloadStorageItem

type HotReloadStorageItem struct {
	Cookies      map[string][]*http.Cookie
	BaseRequest  *BaseRequest
	LoginInfo    *LoginInfo
	WechatDomain WechatDomain
}

type HttpHook

type HttpHook interface {
	BeforeRequest(req *http.Request)
	AfterRequest(response *http.Response, err error)
}

请求上下文钩子

type HttpHooks

type HttpHooks []HttpHook

type JsonFileHotReloadStorage

type JsonFileHotReloadStorage struct {
	// contains filtered or unexported fields
}

实现HotReloadStorage接口 默认以json文件的形式存储

func NewJsonFileHotReloadStorage

func NewJsonFileHotReloadStorage(filename string) *JsonFileHotReloadStorage

func (*JsonFileHotReloadStorage) Dump

将信息写入json文件

func (*JsonFileHotReloadStorage) GetHotReloadStorageItem

func (f *JsonFileHotReloadStorage) GetHotReloadStorageItem() HotReloadStorageItem

func (*JsonFileHotReloadStorage) Load

func (f *JsonFileHotReloadStorage) Load() error

从文件中读取信息

type LoginInfo

type LoginInfo struct {
	Ret         int    `xml:"ret"`
	WxUin       int    `xml:"wxuin"`
	IsGrayScale int    `xml:"isgrayscale"`
	Message     string `xml:"message"`
	SKey        string `xml:"skey"`
	WxSid       string `xml:"wxsid"`
	PassTicket  string `xml:"pass_ticket"`
}

登录信息

func (LoginInfo) Error

func (l LoginInfo) Error() string

func (LoginInfo) Ok

func (l LoginInfo) Ok() bool

type MPSubscribeMsg

type MPSubscribeMsg struct {
	MPArticleCount int
	Time           int64
	UserName       string
	NickName       string
	MPArticleList  []struct {
		Title  string
		Cover  string
		Digest string
		Url    string
	}
}

公众号的订阅信息

type Members

type Members []*User

抽象的用户组

func (Members) Count

func (m Members) Count() int

统计数量

func (Members) First

func (m Members) First() *User

获取第一个

func (Members) Friends

func (m Members) Friends() Friends

func (Members) Groups

func (m Members) Groups() Groups

func (Members) Last

func (m Members) Last() *User

获取最后一个

func (Members) MPs

func (m Members) MPs() Mps

func (Members) Search

func (m Members) Search(limit int, condFuncList ...func(user *User) bool) (results Members)

根据自定义条件查找

func (Members) SearchByNickName

func (m Members) SearchByNickName(limit int, nickName string) (results Members)

根据昵称查找

func (Members) SearchByRemarkName

func (m Members) SearchByRemarkName(limit int, remarkName string) (results Members)

根据备注查找

func (Members) SearchByUserName

func (m Members) SearchByUserName(limit int, username string) (results Members)

根据用户名查找

func (Members) SetOwner

func (m Members) SetOwner(s *Self)

设置owner 请不要随意设置

type Message

type Message struct {
	IsAt    bool
	AppInfo struct {
		Type  int
		AppID string
	}
	AppMsgType           int
	HasProductId         int
	ImgHeight            int
	ImgStatus            int
	ImgWidth             int
	ForwardFlag          int
	MsgType              int
	Status               int
	StatusNotifyCode     int
	SubMsgType           int
	VoiceLength          int
	CreateTime           int64
	NewMsgId             int64
	PlayLength           int64
	MediaId              string
	MsgId                string
	EncryFileName        string
	FileName             string
	FileSize             string
	Content              string
	FromUserName         string
	OriContent           string
	StatusNotifyUserName string
	Ticket               string
	ToUserName           string
	Url                  string

	RecommendInfo RecommendInfo
	Bot           *Bot

	Context context.Context
	// contains filtered or unexported fields
}

func (*Message) Agree

func (m *Message) Agree(verifyContents ...string) error

同意好友的请求

func (*Message) Card

func (m *Message) Card() (*Card, error)

获取card类型

func (*Message) FriendAddMessageContent

func (m *Message) FriendAddMessageContent() (*FriendAddMessage, error)

获取FriendAddMessageContent内容

func (*Message) Get

func (m *Message) Get(key string) (value interface{}, exist bool)

从消息上下文中获取值 goroutine safe

func (*Message) GetFile

func (m *Message) GetFile() (*http.Response, error)

获取文件消息的文件

func (*Message) HasFile

func (m *Message) HasFile() bool

判断消息是否为文件类型的消息

func (*Message) IsCard

func (m *Message) IsCard() bool

func (*Message) IsFriendAdd

func (m *Message) IsFriendAdd() bool

func (*Message) IsMap

func (m *Message) IsMap() bool

func (*Message) IsMedia

func (m *Message) IsMedia() bool

func (*Message) IsNotify

func (m *Message) IsNotify() bool

func (*Message) IsPicture

func (m *Message) IsPicture() bool

func (*Message) IsRecalled

func (m *Message) IsRecalled() bool

判断是否撤回

func (*Message) IsReceiveRedPacket

func (m *Message) IsReceiveRedPacket() bool

判断当前是否收到红包

func (*Message) IsSendByFriend

func (m *Message) IsSendByFriend() bool

判断消息是否由好友发送

func (*Message) IsSendByGroup

func (m *Message) IsSendByGroup() bool

判断消息是否由群组发送

func (*Message) IsSendBySelf

func (m *Message) IsSendBySelf() bool

判断消息是否由自己发送

func (*Message) IsSendRedPacket

func (m *Message) IsSendRedPacket() bool

否发出红包判断当前是

func (*Message) IsSysNotice

func (m *Message) IsSysNotice() bool

func (*Message) IsSystem

func (m *Message) IsSystem() bool

func (*Message) IsText

func (m *Message) IsText() bool

func (*Message) IsTransferAccounts

func (m *Message) IsTransferAccounts() bool

判断当前的消息是不是微信转账

func (*Message) IsVideo

func (m *Message) IsVideo() bool

func (*Message) IsVoice

func (m *Message) IsVoice() bool

func (*Message) Receiver

func (m *Message) Receiver() (*User, error)

获取消息的接收者

func (*Message) Reply

func (m *Message) Reply(msgType int, content, mediaId string) (*SentMessage, error)

回复消息

func (*Message) ReplyFile

func (m *Message) ReplyFile(file *os.File) (*SentMessage, error)

回复文件消息

func (*Message) ReplyImage

func (m *Message) ReplyImage(file *os.File) (*SentMessage, error)

回复图片消息

func (*Message) ReplyText

func (m *Message) ReplyText(content string) (*SentMessage, error)

回复文本消息

func (*Message) RevokeMsg

func (m *Message) RevokeMsg() (*RevokeMsg, error)

获取撤回消息的内容

func (*Message) Sender

func (m *Message) Sender() (*User, error)

获取消息的发送者

func (*Message) SenderInGroup

func (m *Message) SenderInGroup() (*User, error)

获取消息在群里面的发送者

func (*Message) Set

func (m *Message) Set(key string, value interface{})

往消息上下文中设置值 goroutine safe

func (*Message) StatusNotify

func (m *Message) StatusNotify() bool

判断是否为操作通知消息

type MessageContext

type MessageContext struct {
	*Message
	// contains filtered or unexported fields
}

MessageContext 消息处理上下文对象

func (*MessageContext) Next

func (c *MessageContext) Next()

主动调用下一个消息处理函数(或开始调用)

type MessageContextHandler

type MessageContextHandler func(ctx *MessageContext)

MessageMatchDispatcher 消息处理函数

type MessageContextHandlerGroup

type MessageContextHandlerGroup []MessageContextHandler

type MessageDispatcher

type MessageDispatcher interface {
	Dispatch(msg *Message)
}

消息分发处理接口 跟 DispatchMessage 结合封装成 MessageHandler

type MessageHandler

type MessageHandler func(msg *Message)

消息处理函数

type MessageMatchDispatcher

type MessageMatchDispatcher struct {
	// contains filtered or unexported fields
}

MessageMatchDispatcher impl MessageDispatcher interface

dispatcher := NewMessageMatchDispatcher()
dispatcher.OnText(func(msg *Message){
		msg.ReplyText("hello")
})
bot := DefaultBot()
bot.MessageHandler = DispatchMessage(dispatcher)

func NewMessageMatchDispatcher

func NewMessageMatchDispatcher() *MessageMatchDispatcher

Constructor for MessageMatchDispatcher

func (*MessageMatchDispatcher) Dispatch

func (m *MessageMatchDispatcher) Dispatch(msg *Message)

Dispatch impl MessageDispatcher 遍历 MessageMatchDispatcher 所有的消息处理函数 获取所有匹配上的函数 执行处理的消息处理方法

func (*MessageMatchDispatcher) OnCard

func (m *MessageMatchDispatcher) OnCard(handlers ...MessageContextHandler)

注册处理消息类型为Card的处理函数

func (*MessageMatchDispatcher) OnFriend

func (m *MessageMatchDispatcher) OnFriend(handlers ...MessageContextHandler)

注册发送者为好友的处理函数

func (*MessageMatchDispatcher) OnFriendAdd

func (m *MessageMatchDispatcher) OnFriendAdd(handlers ...MessageContextHandler)

注册处理消息类型为FriendAdd的处理函数

func (*MessageMatchDispatcher) OnFriendByNickName

func (m *MessageMatchDispatcher) OnFriendByNickName(nickName string, handlers ...MessageContextHandler)

注册根据好友昵称是否匹配的消息处理函数

func (*MessageMatchDispatcher) OnFriendByRemarkName

func (m *MessageMatchDispatcher) OnFriendByRemarkName(remarkName string, handlers ...MessageContextHandler)

注册根据好友备注是否匹配的消息处理函数

func (*MessageMatchDispatcher) OnGroup

func (m *MessageMatchDispatcher) OnGroup(handlers ...MessageContextHandler)

注册发送者为群组的处理函数

func (*MessageMatchDispatcher) OnGroupByGroupName

func (m *MessageMatchDispatcher) OnGroupByGroupName(groupName string, handlers ...MessageContextHandler)

注册根据群名是否匹配的消息处理函数

func (*MessageMatchDispatcher) OnImage

func (m *MessageMatchDispatcher) OnImage(handlers ...MessageContextHandler)

注册处理消息类型为Image的处理函数

func (*MessageMatchDispatcher) OnText

func (m *MessageMatchDispatcher) OnText(handlers ...MessageContextHandler)

注册处理消息类型为Text的处理函数

func (*MessageMatchDispatcher) OnUser

func (m *MessageMatchDispatcher) OnUser(f func(user *User) bool, handlers ...MessageContextHandler)

注册根据消息发送者的行为是否匹配的消息处理函数

func (*MessageMatchDispatcher) OnVoice

func (m *MessageMatchDispatcher) OnVoice(handlers ...MessageContextHandler)

注册处理消息类型为Voice的处理函数

func (*MessageMatchDispatcher) RegisterHandler

func (m *MessageMatchDispatcher) RegisterHandler(matchFunc matchFunc, handlers ...MessageContextHandler)

注册消息处理函数, 根据自己的需求自定义 matchFunc返回true则表示处理对应的handlers

func (*MessageMatchDispatcher) SetAsync

func (m *MessageMatchDispatcher) SetAsync(async bool)

设置是否异步处理

type MessageResponse

type MessageResponse struct {
	BaseResponse BaseResponse
	LocalID      string
	MsgID        string
}

type Mp

type Mp struct{ *User }

公众号对象

func (Mp) String

func (m Mp) String() string

type Mps

type Mps []*Mp

公众号组对象

func (Mps) Count

func (m Mps) Count() int

数量统计

func (Mps) First

func (m Mps) First() *Mp

获取第一个

func (Mps) Last

func (m Mps) Last() *Mp

获取最后一个

func (Mps) Search

func (m Mps) Search(limit int, condFuncList ...func(group *Mp) bool) (results Mps)

根据自定义条件查找

type RecommendInfo

type RecommendInfo struct {
	OpCode     int
	Scene      int
	Sex        int
	VerifyFlag int
	AttrStatus int64
	QQNum      int64
	Alias      string
	City       string
	Content    string
	NickName   string
	Province   string
	Signature  string
	Ticket     string
	UserName   string
}

一些特殊类型的消息会携带该结构体信息

type RevokeMsg

type RevokeMsg struct {
	SysMsg    xml.Name `xml:"sysmsg"`
	Type      string   `xml:"type,attr"`
	RevokeMsg struct {
		OldMsgId   int64  `xml:"oldmsgid"`
		MsgId      int64  `xml:"msgid"`
		Session    string `xml:"session"`
		ReplaceMsg string `xml:"replacemsg"`
	} `xml:"revokemsg"`
}

撤回消息Content

type Self

type Self struct {
	*User
	Bot *Bot
	// contains filtered or unexported fields
}

自己,当前登录用户对象

func (*Self) AddFriendIntoManyGroups

func (s *Self) AddFriendIntoManyGroups(friend *Friend, groups ...*Group) error

拉好友进多个群聊 AddFriendIntoGroups, 名字和上面的有点像

func (*Self) AddFriendsIntoGroup

func (s *Self) AddFriendsIntoGroup(group *Group, friends ...*Friend) error

拉多名好友进群 最好自己是群主,成功率高一点,因为有的群允许非群组拉人,而有的群不允许

func (*Self) FileHelper

func (s *Self) FileHelper() (*Friend, error)

获取文件传输助手对象,封装成Friend返回

fh, err := self.FileHelper() // or fh := openwechat.NewFriendHelper(self)

func (*Self) ForwardMessageToFriends

func (s *Self) ForwardMessageToFriends(msg *SentMessage, friends ...*Friend) error

转发给好友

func (*Self) ForwardMessageToGroups

func (s *Self) ForwardMessageToGroups(msg *SentMessage, groups ...*Group) error

转发给群组

func (*Self) Friends

func (s *Self) Friends(update ...bool) (Friends, error)

获取所有的好友

func (*Self) Groups

func (s *Self) Groups(update ...bool) (Groups, error)

获取所有的群组

func (*Self) Members

func (s *Self) Members(update ...bool) (Members, error)

获取所有的好友、群组、公众号信息

func (*Self) Mps

func (s *Self) Mps(update ...bool) (Mps, error)

获取所有的公众号

func (*Self) RemoveMemberFromGroup

func (s *Self) RemoveMemberFromGroup(group *Group, members Members) error

从群聊中移除用户 Deprecated 无论是网页版,还是程序上都不起作用

func (*Self) RevokeMessage

func (s *Self) RevokeMessage(msg *SentMessage) error

撤回消息

sentMessage, err := friend.SendText("message")
if err == nil {
    self.RevokeMessage(sentMessage) // or sentMessage.Revoke()
}

func (*Self) SendFileToFriend

func (s *Self) SendFileToFriend(friend *Friend, file *os.File) (*SentMessage, error)

发送文件给好友

func (*Self) SendFileToGroup

func (s *Self) SendFileToGroup(group *Group, file *os.File) (*SentMessage, error)

发送文件给群组

func (*Self) SendImageToFriend

func (s *Self) SendImageToFriend(friend *Friend, file *os.File) (*SentMessage, error)

发送图片消息给好友

func (*Self) SendImageToGroup

func (s *Self) SendImageToGroup(group *Group, file *os.File) (*SentMessage, error)

发送图片消息给群组

func (*Self) SendMessageToFriend

func (s *Self) SendMessageToFriend(friend *Friend, msg *SendMessage) (*SentMessage, error)

发送消息给好友

func (*Self) SendMessageToGroup

func (s *Self) SendMessageToGroup(group *Group, msg *SendMessage) (*SentMessage, error)

发送消息给群组

func (*Self) SendTextToFriend

func (s *Self) SendTextToFriend(friend *Friend, text string) (*SentMessage, error)

发送文本消息给好友

func (*Self) SendTextToGroup

func (s *Self) SendTextToGroup(group *Group, text string) (*SentMessage, error)

发送文本消息给群组

func (*Self) SetRemarkNameToFriend

func (s *Self) SetRemarkNameToFriend(friend *Friend, remarkName string) error

设置好友备注

self.SetRemarkNameToFriend(friend, "remark") // or friend.SetRemarkName("remark")

func (*Self) UpdateMembersDetail

func (s *Self) UpdateMembersDetail() error

更新所有的联系人信息

type SendMessage

type SendMessage struct {
	Type         int
	Content      string
	FromUserName string
	ToUserName   string
	LocalID      string
	ClientMsgId  string
	MediaId      string `json:"MediaId,omitempty"`
}

发送消息的结构体

func NewMediaSendMessage

func NewMediaSendMessage(msgType int, fromUserName, toUserName, mediaId string) *SendMessage

媒体消息的构造方法

func NewSendMessage

func NewSendMessage(msgType int, content, fromUserName, toUserName, mediaId string) *SendMessage

SendMessage的构造方法

func NewTextSendMessage

func NewTextSendMessage(content, fromUserName, toUserName string) *SendMessage

文本消息的构造方法

type SentMessage

type SentMessage struct {
	*SendMessage
	Self  *Self
	MsgId string
}

已发送的信息

func (*SentMessage) ForwardToFriends

func (s *SentMessage) ForwardToFriends(friends ...*Friend) error

转发该消息给好友

func (*SentMessage) ForwardToGroups

func (s *SentMessage) ForwardToGroups(groups ...*Group) error

转发该消息给群组

func (*SentMessage) Revoke

func (s *SentMessage) Revoke() error

撤回该消息

type Storage

type Storage struct {
	LoginInfo *LoginInfo
	Request   *BaseRequest
	Response  *WebInitResponse
}

身份信息, 维持整个登陆的Session会话

type SyncCheckResponse

type SyncCheckResponse struct {
	RetCode  string
	Selector string
}

func (*SyncCheckResponse) Error

func (s *SyncCheckResponse) Error() string

实现error接口

func (*SyncCheckResponse) NorMal

func (s *SyncCheckResponse) NorMal() bool

func (*SyncCheckResponse) Success

func (s *SyncCheckResponse) Success() bool

type SyncKey

type SyncKey struct {
	Count int
	List  []struct{ Key, Val int64 }
}

type UploadResponse

type UploadResponse struct {
	BaseResponse BaseResponse
	MediaId      string
}

type User

type User struct {
	Uin               int
	HideInputBarFlag  int
	StarFriend        int
	Sex               int
	AppAccountFlag    int
	VerifyFlag        int
	ContactFlag       int
	WebWxPluginSwitch int
	HeadImgFlag       int
	SnsFlag           int
	IsOwner           int
	MemberCount       int
	ChatRoomId        int
	UniFriend         int
	OwnerUin          int
	Statues           int
	AttrStatus        int
	Province          string
	City              string
	Alias             string
	DisplayName       string
	KeyWord           string
	EncryChatRoomId   string
	UserName          string
	NickName          string
	HeadImgUrl        string
	RemarkName        string
	PYInitial         string
	PYQuanPin         string
	RemarkPYInitial   string
	RemarkPYQuanPin   string
	Signature         string

	MemberList Members

	Self *Self
}

抽象的用户结构: 好友 群组 公众号

func (*User) Detail

func (u *User) Detail() (*User, error)

获取用户的详情

func (*User) GetAvatarResponse

func (u *User) GetAvatarResponse() (*http.Response, error)

获取用户头像

func (*User) IsFriend

func (u *User) IsFriend() bool

判断是否为好友

func (*User) IsGroup

func (u *User) IsGroup() bool

判断是否为群组

func (*User) IsMP

func (u *User) IsMP() bool

判断是否为公众号

func (*User) SaveAvatar

func (u *User) SaveAvatar(filename string) error

下载用户头像

func (*User) String

func (u *User) String() string

implement fmt.Stringer

type UserAgentHook

type UserAgentHook struct{}

func (UserAgentHook) AfterRequest

func (u UserAgentHook) AfterRequest(response *http.Response, err error)

func (UserAgentHook) BeforeRequest

func (u UserAgentHook) BeforeRequest(req *http.Request)

type UserDetailItem

type UserDetailItem struct {
	UserName        string
	EncryChatRoomId string
}

type UserDetailItemList

type UserDetailItemList []UserDetailItem

func NewUserDetailItemList

func NewUserDetailItemList(members Members) UserDetailItemList

type WebInitResponse

type WebInitResponse struct {
	Count               int
	ClientVersion       int
	GrayScale           int
	InviteStartCount    int
	MPSubscribeMsgCount int
	ClickReportInterval int
	SystemTime          int64
	ChatSet             string
	SKey                string
	BaseResponse        BaseResponse
	SyncKey             SyncKey
	User                User
	MPSubscribeMsgList  []MPSubscribeMsg
	ContactList         []User
}

初始化的相应信息

type WebWxBatchContactResponse

type WebWxBatchContactResponse struct {
	Count        int
	BaseResponse BaseResponse
	ContactList  []*User
}

type WebWxContactResponse

type WebWxContactResponse struct {
	MemberCount  int
	Seq          int
	BaseResponse BaseResponse
	MemberList   []*User
}

type WebWxSyncResponse

type WebWxSyncResponse struct {
	AddMsgCount            int
	ContinueFlag           int
	DelContactCount        int
	ModChatRoomMemberCount int
	ModContactCount        int
	Skey                   string
	SyncCheckKey           SyncKey
	SyncKey                SyncKey
	BaseResponse           BaseResponse
	ModChatRoomMemberList  Members
	AddMsgList             []*Message
}

type WechatDomain

type WechatDomain string

func (WechatDomain) BaseHost

func (w WechatDomain) BaseHost() string

func (WechatDomain) FileHost

func (w WechatDomain) FileHost() string

func (WechatDomain) SyncHost

func (w WechatDomain) SyncHost() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL