diff --git a/wechat-contact.ahk b/wechat-contact.ahk index a0593b9..f3f5171 100644 --- a/wechat-contact.ahk +++ b/wechat-contact.ahk @@ -21,10 +21,6 @@ _projectUrl := "https://github.com/XgHao/WeChat-Contact" ;项目地址 class CopyError extends Error {} -; 自定义异常-老版本异常 -class OldVersionError extends Error -{} - ; 自定义异常-微信窗口异常 class WeChatWinError extends Error {} @@ -61,14 +57,7 @@ msgbox("1.win+c开始导出`r`n2.win+ecs停止", "说明", "OK") path := CreateFilePath() ; 保存为Csv - try - { - SaveContactToCsv(path, contactCount) - } - catch OldVersionError as oldVersionErr ;老版本不能全选复制,需要模拟复制 - { - SaveContactToCsv_Old(path, contactCount) - } + SaveContactToCsv(path, contactCount) } catch WeChatWinError as weChatWinErr ;微信窗口异常 { @@ -120,7 +109,8 @@ SetWeChatWin() Sleep 100 ; 定位到最后一个微信好友 - click Format("{1} {2} Middle", _contactListX, _contactListY) + click _contactListX, _contactListY + ; click Format("{1} {2} Middle", _contactListX, _contactListY) Sleep 100 send "{End}" } @@ -168,291 +158,183 @@ GetContactDetail() { A_Clipboard := "" ;清空剪切板 Sleep 10 ;缓冲时间 - sendinput "^a" ;全选 - Sleep 10 ;缓冲时间 - SendInput "^c" ;复制 - if !ClipWait(0.5, 0) ;等待0.5s超时视为失败,使用老版本 + sendinput "^a^c" ;全选复制 + Sleep 20 ;缓冲时间 + if !ClipWait(0.5, 0) ;等待1s超时视为失败,使用老版本 Throw CopyError("copy error") + data := A_Clipboard contactMap := Map() ;新建Map对象,存放联系人信息 - wechatDetailArr := StrSplit(A_Clipboard, "`n") ;通过换行符进行分割 + wechatDetailArr := StrSplit(data, "`n") ;通过换行符进行分割 len := wechatDetailArr.Length switch len { - default: + case 8: ;wechatDetailArr[7]是描述 { - ; 企业用户 - if (SubStr(wechatDetailArr[2], 1, 1) = "@") - { - if (SubStr(wechatDetailArr[2], 2) = wechatDetailArr[3]) ;有无备注 - 企业名称之前有无信息 - { - contactMap[1] := "-" ;备注 - contactMap[2] := wechatDetailArr[1] ;昵称 - contactMap[3] := wechatDetailArr[2] ;微信ID - contactMap[4] := "-" ;地区 - contactMap[5] := "-" ;标签或描述 - contactMap[6] := wechatDetailArr[5] . " " . wechatDetailArr[6] . " " . wechatDetailArr[7] . " " . wechatDetailArr[8] ;企业微信 - } - else - { - contactMap[1] := wechatDetailArr[1] ;备注 - contactMap[2] := wechatDetailArr[3] ;昵称 - contactMap[3] := wechatDetailArr[5] ;微信ID - contactMap[4] := "-" ;地区 - contactMap[5] := "-" ;标签或描述 - contactMap[6] := "-" ;企业微信 - } - } - else - { - ;默认 - } + contactMap[1] := wechatDetailArr[1] ;备注 + contactMap[2] := wechatDetailArr[2] ;昵称 + contactMap[3] := wechatDetailArr[3] ;微信ID + contactMap[4] := wechatDetailArr[4] ;地区 + contactMap[5] := wechatDetailArr[6] ;标签 + contactMap[6] := wechatDetailArr[8] ;个性签名 + } + case 7: + { + contactMap[1] := wechatDetailArr[1] ;备注 + contactMap[2] := wechatDetailArr[2] ;昵称 + contactMap[3] := wechatDetailArr[3] ;微信ID + contactMap[4] := wechatDetailArr[4] ;地区 + contactMap[5] := wechatDetailArr[6] ;标签 + contactMap[6] := wechatDetailArr[7] ;个性签名 } - - case 7: ; 包含描述 + case 6: { - ; 企业用户 - if (SubStr(wechatDetailArr[2], 1, 1) = "@") + ; 有备注,但是没有地区信息,最后两个可以是【地区,标签,描述,个性签名】中任意两个,默认给最大可能性 【标签,个性签名】 + if (wechatDetailArr[1] = wechatDetailArr[4]) { - if (SubStr(wechatDetailArr[2], 2) = wechatDetailArr[3]) ;有无备注 - 企业名称之前有无信息 - { - contactMap[1] := "-" ;备注 - contactMap[2] := wechatDetailArr[1] ;昵称 - contactMap[3] := wechatDetailArr[2] ;微信ID - contactMap[4] := "-" ;地区 - contactMap[5] := "-" ;标签或描述 - contactMap[6] := wechatDetailArr[4] . " " . wechatDetailArr[5] . " " . wechatDetailArr[6] . " " . wechatDetailArr[7] ;企业微信 - } - else - { - contactMap[1] := wechatDetailArr[1] ;备注 - contactMap[2] := wechatDetailArr[3] ;昵称 - contactMap[3] := wechatDetailArr[2] ;微信ID - contactMap[4] := "-" ;地区 - contactMap[5] := "-" ;标签或描述 - contactMap[6] := wechatDetailArr[6] . " " . wechatDetailArr[7] ;企业微信 - } + contactMap[1] := wechatDetailArr[1] ;备注 + contactMap[2] := wechatDetailArr[2] ;昵称 + contactMap[3] := wechatDetailArr[3] ;微信ID + contactMap[4] := "-" ;地区 + contactMap[5] := wechatDetailArr[5] ;标签 + contactMap[6] := wechatDetailArr[6] ;个性签名 } - else + + ; 有备注,地区信息,最后两个可以是【地区,标签,描述,个性签名】中任意一个 + else if (wechatDetailArr[1] = wechatDetailArr[5]) { contactMap[1] := wechatDetailArr[1] ;备注 contactMap[2] := wechatDetailArr[2] ;昵称 contactMap[3] := wechatDetailArr[3] ;微信ID contactMap[4] := wechatDetailArr[4] ;地区 - contactMap[5] := Format("标签:{1} 描述:{2}", wechatDetailArr[6], wechatDetailArr[7]) ;标签或描述 - contactMap[6] := "-" ;企业微信 - } - } - case 6: ; 所有信息 - { - ; 企业用户 - if (SubStr(wechatDetailArr[2], 1, 1) = "@") - { - if (SubStr(wechatDetailArr[2], 2) = wechatDetailArr[3]) ;有无备注 - 企业名称之前有无信息 + if (StrLen(wechatDetailArr[6]) >= 5) { - contactMap[1] := "-" ;备注 - contactMap[2] := wechatDetailArr[1] ;昵称 - contactMap[3] := wechatDetailArr[2] ;微信ID - contactMap[4] := "-" ;地区 - contactMap[5] := "-" ;标签或描述 - contactMap[6] := wechatDetailArr[4] . " " . wechatDetailArr[5] . " " . wechatDetailArr[6] ;企业微信 - + contactMap[5] := "-" ;标签 + contactMap[6] := wechatDetailArr[6] ;个性签名 } else { - contactMap[1] := wechatDetailArr[1] ;备注 - contactMap[2] := wechatDetailArr[3] ;昵称 - contactMap[3] := wechatDetailArr[2] ;微信ID - contactMap[4] := "-" ;地区 - contactMap[5] := "-" ;标签或描述 - contactMap[6] := wechatDetailArr[6] ;企业微信 + contactMap[5] := wechatDetailArr[6] ;标签 + contactMap[6] := "-" ;个性签名 } } + + ; 没有备注,wechatDetailArr[5]是描述 else { - if (wechatDetailArr[1] = wechatDetailArr[5]) ; 无标签或描述 - { - contactMap[1] := wechatDetailArr[1] ;备注 - contactMap[2] := wechatDetailArr[2] ;昵称 - contactMap[3] := wechatDetailArr[3] ;微信ID - contactMap[4] := wechatDetailArr[4] ;地区 - contactMap[5] := wechatDetailArr[6] ;标签或描述 - contactMap[6] := "-" ;企业微信 - } - else ;无地区 - { - contactMap[1] := wechatDetailArr[1] ;备注 - contactMap[2] := wechatDetailArr[2] ;昵称 - contactMap[3] := wechatDetailArr[3] ;微信ID - contactMap[4] := "-" ;地区 - contactMap[5] := Format("标签:{1} 描述:{2}", wechatDetailArr[5], wechatDetailArr[6]) ;标签或描述 - contactMap[6] := "-" ;企业微信 - } + contactMap[1] := "-" ;备注 + contactMap[2] := wechatDetailArr[1] ;昵称 + contactMap[3] := wechatDetailArr[2] ;微信ID + contactMap[4] := wechatDetailArr[3] ;地区 + contactMap[5] := wechatDetailArr[4] ;标签 + contactMap[6] := wechatDetailArr[6] ;个性签名 } } - case 5: ; 无标签或无地区 + case 5: { - ; 企业用户 - if (SubStr(wechatDetailArr[2], 1, 1) = "@") + ; 有备注,但是没有地区信息,最后一个可能是标签或个性签名,这里根据长度判断 + if (wechatDetailArr[1] = wechatDetailArr[4]) { - if (SubStr(wechatDetailArr[2], 2) = wechatDetailArr[3]) ;有无备注 - 企业名称之前有无信息 + contactMap[1] := wechatDetailArr[1] ;备注 + contactMap[2] := wechatDetailArr[2] ;昵称 + contactMap[3] := wechatDetailArr[3] ;微信ID + contactMap[4] := "-" ;地区 + if (StrLen(wechatDetailArr[5]) >= 5) { - contactMap[1] := "-" ;备注 - contactMap[2] := wechatDetailArr[1] ;昵称 - contactMap[3] := wechatDetailArr[2] ;微信ID - contactMap[4] := "-" ;地区 - contactMap[5] := "-" ;标签或描述 - contactMap[6] := wechatDetailArr[3] . " " . wechatDetailArr[4] . " " . wechatDetailArr[5] ;企业微信 + contactMap[5] := "-" ;标签 + contactMap[6] := wechatDetailArr[5] ;个性签名 } else { - contactMap[1] := wechatDetailArr[1] ;备注 - contactMap[2] := wechatDetailArr[3] ;昵称 - contactMap[3] := wechatDetailArr[5] ;微信ID - contactMap[4] := "-" ;地区 - contactMap[5] := "-" ;标签或描述 - contactMap[6] := "-" ;企业微信 + contactMap[5] := wechatDetailArr[5] ;标签 + contactMap[6] := "-" ;个性签名 } } - else + + ; 有备注,地区信息 + else if (wechatDetailArr[1] = wechatDetailArr[5]) { - if (wechatDetailArr[1] = wechatDetailArr[5]) ; 无标签或描述 - { - contactMap[1] := wechatDetailArr[1] ;备注 - contactMap[2] := wechatDetailArr[2] ;昵称 - contactMap[3] := wechatDetailArr[3] ;微信ID - contactMap[4] := wechatDetailArr[4] ;地区 - contactMap[5] := "-" ;标签或描述 - contactMap[6] := "-" ;企业微信 - } - else if (wechatDetailArr[1] = wechatDetailArr[4]) ; 无地区 - { - contactMap[1] := wechatDetailArr[1] ;备注 - contactMap[2] := wechatDetailArr[2] ;昵称 - contactMap[3] := wechatDetailArr[3] ;微信ID - contactMap[4] := "-" ;地区 - contactMap[5] := wechatDetailArr[5] ;标签或描述 - contactMap[6] := "-" ;企业微信 - } - else ;无备注 - { - contactMap[1] := "-" ;备注 - contactMap[2] := wechatDetailArr[1] ;昵称 - contactMap[3] := wechatDetailArr[2] ;微信ID - contactMap[4] := wechatDetailArr[3] ;地区 - contactMap[5] := Format("标签:{1} 描述:{2}", wechatDetailArr[4], wechatDetailArr[5]) ;标签或描述 - contactMap[6] := "-" ;企业微信 - } + contactMap[1] := wechatDetailArr[1] ;备注 + contactMap[2] := wechatDetailArr[2] ;昵称 + contactMap[3] := wechatDetailArr[3] ;微信ID + contactMap[4] := wechatDetailArr[4] ;地区 + contactMap[5] := "-" ;标签 + contactMap[6] := "-" ;个性签名 } - } - case 4: ;无备注 或 无标签无地区 - { - ; 企业用户 - if (SubStr(wechatDetailArr[2], 1, 1) = "@") + + ; 没有备注,能确定的只有昵称ID,后续可以是【地区,标签,描述,个性签名】中任意三个,默认给最大可能性 【地区,标签,个性签名】 + else { contactMap[1] := "-" ;备注 contactMap[2] := wechatDetailArr[1] ;昵称 contactMap[3] := wechatDetailArr[2] ;微信ID - contactMap[4] := "-" ;地区 - contactMap[5] := "-" ;标签或描述 - contactMap[6] := wechatDetailArr[4] ;企业微信 - } - else - { - if (wechatDetailArr[1] = wechatDetailArr[4]) ; 无标签 无地区 - { - contactMap[1] := wechatDetailArr[1] ;备注 - contactMap[2] := wechatDetailArr[2] ;昵称 - contactMap[3] := wechatDetailArr[3] ;微信ID - contactMap[4] := "-" ;地区 - contactMap[5] := "-" ;标签或描述 - contactMap[6] := "-" ;企业微信 - } - else ;无备注 - { - if (InStr(wechatDetailArr[3], " ")) ; 包含空格 视为地区 - { - contactMap[1] := "-" ;备注 - contactMap[2] := wechatDetailArr[1] ;昵称 - contactMap[3] := wechatDetailArr[2] ;微信ID - contactMap[4] := wechatDetailArr[3] ;地区 - contactMap[5] := wechatDetailArr[4] ;标签或描述 - contactMap[6] := "-" ;企业微信 - } - else ;无地区 - { - contactMap[1] := "-" ;备注 - contactMap[2] := wechatDetailArr[1] ;昵称 - contactMap[3] := wechatDetailArr[2] ;微信ID - contactMap[4] := "-" ;地区 - contactMap[5] := Format("标签:{1} 描述:{2}", wechatDetailArr[3], wechatDetailArr[4]) ;标签或描述 - contactMap[6] := "-" ;企业微信 - } - } + contactMap[4] := wechatDetailArr[3] ;地区 + contactMap[5] := wechatDetailArr[4] ;标签 + contactMap[6] := wechatDetailArr[5] ;个性签名 } } - case 3: ; 无备注无地区或无备注无标签 TODO: 目前不能区分 + case 4: ; 备注 + 昵称微信ID 或者 昵称 { - ; 企业用户 - if (SubStr(wechatDetailArr[2], 1, 1) = "@") + ; 有备注,但是没有地区信息 + if (wechatDetailArr[1] = wechatDetailArr[4]) { - contactMap[1] := "-" ;备注 - contactMap[2] := wechatDetailArr[1] ;昵称 - contactMap[3] := wechatDetailArr[2] ;微信ID + contactMap[1] := wechatDetailArr[1] ;备注 + contactMap[2] := wechatDetailArr[2] ;昵称 + contactMap[3] := wechatDetailArr[3] ;微信ID contactMap[4] := "-" ;地区 - contactMap[5] := "-" ;标签或描述 - contactMap[6] := wechatDetailArr[1] ;企业微信 + contactMap[5] := "-" ;标签 + contactMap[6] := "-" ;个性签名 } - else + + ; 无备注,只能确定昵称及ID,后续可以是【地区,标注,描述,个性签名】中任意连续两个,默认给最大可能性 【地区,个性签名】 + if (wechatDetailArr[1] != wechatDetailArr[4]) { - if (InStr(wechatDetailArr[3], " ")) ; 包含空格 视为地区 - { - contactMap[1] := "-" ;备注 - contactMap[2] := wechatDetailArr[1] ;昵称 - contactMap[3] := wechatDetailArr[2] ;微信ID - contactMap[4] := wechatDetailArr[3] ;地区 - contactMap[5] := "-" ;标签或描述 - contactMap[6] := "-" ;企业微信 - } - else ;无地区 - { - contactMap[1] := "-" ;备注 - contactMap[2] := wechatDetailArr[1] ;昵称 - contactMap[3] := wechatDetailArr[2] ;微信ID - contactMap[4] := "-" ;地区 - contactMap[5] := wechatDetailArr[3] ;标签或描述 - contactMap[6] := "-" ;企业微信 - } + contactMap[1] := "-" ;备注 + contactMap[2] := wechatDetailArr[1] ;昵称 + contactMap[3] := wechatDetailArr[2] ;微信ID + contactMap[4] := wechatDetailArr[3] ;地区 + contactMap[5] := "-" ;标签 + contactMap[6] := wechatDetailArr[4] ;个性签名 } } - case 2: ; 仅有昵称及ID + case 3: ; 昵称,微信ID,地区(无法区分企业微信) { contactMap[1] := "-" ;备注 contactMap[2] := wechatDetailArr[1] ;昵称 contactMap[3] := wechatDetailArr[2] ;微信ID - contactMap[4] := "-" ;地区 + contactMap[4] := wechatDetailArr[3] ;地区 contactMap[5] := "-" ;标签或描述 - contactMap[6] := "-" ;企业微信 + contactMap[6] := "-" ;个性签名 + } + case 2: ; 仅有昵称及微信ID + { + contactMap[1] := "-" ;备注 + contactMap[2] := wechatDetailArr[1] ;昵称 + contactMap[3] := wechatDetailArr[2] ;微信ID + contactMap[4] := "-" ;地区 + contactMap[5] := "-" ;标签 + contactMap[6] := "-" ;个性签名 } } + ; 元数据 + contactMap[7] := data + ; 移动到上一个 send "{Up}" Sleep 50 ;缓存时间等待下个联系人加载 + Return contactMap } ;保存联系人为Csv SaveContactToCsv(path, contactCount) { - ; 校验版本 - CheckVersion() - fileName := Format("{1}\{2}.csv", path, A_Now) ;文件名 csvFile := FileOpen(fileName, "w", "UTF-8") ; 标题 - csvFile.WriteLine("昵称,微信号,备注,地区,标签或描述,企业微信额外信息") + csvFile.WriteLine("备注,昵称,微信号,地区,标签,个性签名,元数据") errorCount := 0 ;失败次数,当连续3次失败后,视为导出完成 loop { @@ -462,7 +344,7 @@ SaveContactToCsv(path, contactCount) contactCount-- ;写入成功,自减1 errorCount := 0 ;成功后失败次数归零,重新计数 } - catch + catch as e { if (++errorCount > 3) ;自增失败次数 Break ;联系失败3次,视为导出成功 @@ -478,7 +360,7 @@ SaveContactToCsv(path, contactCount) FormatContactCsv(map) { - return Format("{1},{2},{3},{4},{5},{6}", FormatCsvItem(map[2]), FormatCsvItem(map[3]), FormatCsvItem(map[1]), FormatCsvItem(map[4]), FormatCsvItem(map[5]), FormatCsvItem(map[6])) + return Format("{1},{2},{3},{4},{5},{6},{7}", FormatCsvItem(map[1]), FormatCsvItem(map[2]), FormatCsvItem(map[3]), FormatCsvItem(map[4]), FormatCsvItem(map[5]), FormatCsvItem(map[6]), FormatCsvItem(StrReplace(map[7], "`n", " "))) } FormatCsvItem(item) @@ -492,116 +374,8 @@ FormatCsvItem(item) { return "'" . item } - - return item -} - -; 校验是否新版本 -CheckVersion() -{ - A_Clipboard := "" ;清空剪切板 - sendinput "^a^c" ;全选复制 - if !ClipWait(0.5, 1) ;等待0.5s超时视为失败,使用老版本 - Throw OldVersionError("old version") -} - -;#endregion - - -;#region 老版本获取方式 [version < 3.7.0] - -;移动到下一个联系人 -MoveToNextContact() -{ - click Format("{1} {2} Middle", _contactListX, _contactListY) - send "{Up}" - Sleep 50 ;缓存时间等待下个联系人加载 -} - -;获取联系人详情-老版本 -GetContactDetail_Old() -{ - Loop 3 ;循环3次,若3次还没有复制到内容视为失败 - { - mouseclickdrag "L", _contactDetailLowRightX, _contactDetailLowRightY, _contactDetailUpLeftX, _contactDetailUpLeftY ;选中联系人信息详情 - A_Clipboard := "" ;清空剪切板 - Sleep 50 - sendinput "^c" ;复制 - if ClipWait(0.1, 1) ;超时抛出异常 - Break - } - - contactMap := Map() ;新建Map对象,存放联系人信息 - wechatDetailArr := StrSplit(A_Clipboard, "`n") ;通过换行符进行分割 - - len := wechatDetailArr.Length - if (len = 5) - { - contactMap[1] := wechatDetailArr[1] ;昵称 - contactMap[2] := wechatDetailArr[2] ;签名 - contactMap[3] := wechatDetailArr[3] ;地区 - contactMap[4] := wechatDetailArr[4] ;微信ID - contactMap[5] := wechatDetailArr[5] ;来源 - } - else if (len = 4) ;没有签名的情况 - { - contactMap[1] := wechatDetailArr[1] - contactMap[2] := "" - contactMap[3] := wechatDetailArr[2] - contactMap[4] := wechatDetailArr[3] - contactMap[5] := wechatDetailArr[4] - } - else ;其余数组长度都当做失败 - { - MoveToNextContact() ;移动到下个联系人 - Throw Error("The copy text is error.") ;复制文字失败 - } - - A_Clipboard := "" ;清空剪切板 - click _contactRemarkX, _contactRemarkY - sleep 20 - sendinput "^a^c" ;全选 - ClipWait(0.1, 1) ;等待0.1s超时视为无备注 - contactMap[6] := A_Clipboard ;备注 - MoveToNextContact() ;移动到下个联系人 - - Return contactMap -} - -;保存联系人为Csv-老版本 -SaveContactToCsv_Old(path, contactCount) -{ - fileName := Format("{1}\{2}.csv", path, A_Now) ;文件名 - csvFile := FileOpen(fileName, "w", "UTF-8") - - ; 标题 - csvFile.WriteLine("昵称,签名,地区,微信号,来源,备注") - errorCount := 0 ;失败次数,当连续3次失败后,视为导出完成 - loop - { - try - { - csvFile.WriteLine(FormatContactCsv_Old(GetContactDetail_Old())) - contactCount-- ;写入成功,自减1 - errorCount := 0 ;成功后失败次数归零,重新计数 - } - catch ; TODO 获取联系人信息失败 - { - if (++errorCount > 3) ;自增失败次数 - Break ;联系失败3次,视为导出成功 - } - - ; 当行数大于微信联系人时,导出完毕跳出 - if (contactCount <= 0) - Break - } - csvFile.Close() -} - -FormatContactCsv_Old(map) -{ - return Format("{1},{2},{3},{4},{5}", map[1], map[2], map[3], map[4], map[5]) + return item } ;#endregion