@@ -0,0 +1,185 @@
const db = uniCloud . database ( ) ;
const _ = db . command ;
let obj = {
isValidIP ( ip ) {
// ------------------------- IPv4 验证 -------------------------
if ( ip . includes ( '.' ) ) {
const ipv4Regex = /^(?:(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])$/ ;
return ipv4Regex . test ( ip ) ; // 直接通过正则匹配[1,5](@ref)
}
// ------------------------- IPv6 验证 -------------------------
if ( ip . includes ( ':' ) ) {
const parts = ip . split ( ':' ) ;
// 处理压缩的::符号(如::1或2001:db8::1)
const hasDoubleColon = ip . includes ( '::' ) ;
if ( hasDoubleColon && ip . indexOf ( '::' ) !== ip . lastIndexOf ( '::' ) ) return false ; // 禁止多个::[6](@ref)
// 分割后的段数应在1到8之间(允许压缩)
if ( parts . length < 3 || parts . length > 8 ) return false ;
// 展开压缩段(如将::替换为填充段)
let expandedParts = [ ] ;
let fillZeros = 8 - parts . filter ( p => p !== '' ) . length ;
for ( let part of parts ) {
if ( part === '' ) {
while ( fillZeros -- > 0 ) expandedParts . push ( '0' ) ;
} else {
expandedParts . push ( part ) ;
}
}
if ( expandedParts . length !== 8 ) return false ;
// 验证每段是否为1-4位十六进制字符
const hexRegex = /^[0-9a-fA-F]{1,4}$/ ;
return expandedParts . every ( p => hexRegex . test ( p ) ) ; // 每段必须符合规则[6,7](@ref)
}
return false ;
} ,
isReservedOrLocalIP ( ip ) {
// ------------------------- IPv4 处理逻辑 -------------------------
if ( ip . includes ( '.' ) ) {
const parts = ip . split ( '.' ) . map ( Number ) ;
// 格式验证
if ( parts . length !== 4 || parts . some ( n => n < 0 || n > 255 ) ) return false ;
// 1. 局域网地址(私有地址)
if (
parts [ 0 ] === 10 || // 10.0.0.0/8 [1,2,4](@ref)
( parts [ 0 ] === 172 && parts [ 1 ] >= 16 && parts [ 1 ] <= 31 ) || // 172.16.0.0/12 [1,2,4](@ref)
( parts [ 0 ] === 192 && parts [ 1 ] === 168 ) // 192.168.0.0/16 [1,2,4](@ref)
) return true ;
// 2. 保留地址
return (
parts [ 0 ] === 127 || // 127.0.0.0/8(环回地址)[1,4](@ref)
( parts [ 0 ] === 169 && parts [ 1 ] === 254 ) || // 169.254.0.0/16(链路本地地址)[4,5](@ref)
( parts [ 0 ] >= 224 && parts [ 0 ] <= 239 ) || // 224.0.0.0/4(多播地址)[3,5](@ref)
ip === '0.0.0.0' || // 未指定地址 [1](@ref)
ip === '255.255.255.255' // 广播地址 [1](@ref)
) ;
}
// ------------------------- IPv6 处理逻辑 -------------------------
if ( ip . includes ( ':' ) ) {
// 规范化IPv6(展开缩写)
const normalized = ip . replace ( /(^:|:$)/g , '::' ) . replace ( /::/g , ':0:' ) . split ( ':' )
. map ( seg => seg . padStart ( 4 , '0' ) ) . join ( ':' ) . padStart ( 39 , '0:' ) ;
if ( normalized . startsWith ( 'fc00:' ) || normalized . startsWith ( 'fd00:' ) ) return true ;
// 2. 保留地址
return (
normalized === '0000:0000:0000:0000:0000:0000:0000:0001' ||
normalized . startsWith ( 'fe80:' ) ||
normalized . startsWith ( 'ff00:' ) ||
normalized . startsWith ( '2001:0db8:' ) ||
normalized === '0000:0000:0000:0000:0000:0000:0000:0000'
) ;
}
return false ;
} ,
async getIPAddress ( ip ) {
if ( ! obj . isValidIP ( ip ) ) return "未知" ;
if ( obj . isReservedOrLocalIP ( ip ) ) return "未知" ;
let address = "" ;
const res = await uniCloud . collection ( "ip" ) . where ( {
ip : ip
} )
. get ( ) ;
console . log ( res ) ;
if ( res . data . length > 0 ) {
const res = await uniCloud . collection ( "ip" ) . where ( {
ip : ip
} )
. field ( {
ip : true ,
country : true ,
economize : true ,
market : true ,
} )
. get ( ) ;
if ( res . data [ 0 ] . market === "" ) address = res . data [ 0 ] . country + " " + res . data [ 0 ] . economize ;
else {
address = res . data [ 0 ] . economize + " " + res . data [ 0 ] . market ;
}
return address ;
}
let url = "https://62cccca0.api.cn/ipdata?token=7cec107b2f759a84211c74d9d9d6b4c4&datatype=json&ip=" + ip ;
const response = await uniCloud . httpclient . request ( url , {
method : 'GET' ,
timeout : 1000
} ) ;
console . log ( response ) ;
if ( response . status === 200 ) {
await uniCloud . collection ( "ip" ) . add ( {
ip : response . data . ip ,
country : response . data . data [ 0 ] === "台湾" ? "中国台湾" : response . data . data [ 0 ] ,
economize : response . data . data [ 1 ] ,
market : response . data . data [ 2 ] ,
county : response . data . data [ 3 ] ,
operator : response . data . data [ 4 ] ,
postal _code : response . data . data [ 5 ] ,
area _code : response . data . data [ 6 ] ,
network : response . data . data [ 7 ]
} ) ;
if ( response . data . data [ 2 ] === "" ) {
address = response . data . data [ 0 ] + " " + response . data . data [ 1 ] ;
} else {
address = response . data . data [ 1 ] + " " + response . data . data [ 2 ] ;
}
return address ;
}
return address ;
}
}
module . exports = {
_before : function ( ) { // 通用预处理器
} ,
async get _user _info ( query ) {
try {
let uid = query . uid ;
console . log ( uid ) ;
if ( ! uid ) throw new Error ( "uid不存在" ) ;
console . log ( uid ) ;
let res = await db . collection ( "uni-id-users" )
. doc ( uid )
. field ( {
_id : true ,
nickname : true ,
avatar _file : true ,
last _login _ip : true ,
register _date : true ,
last _login _date : true ,
personal _profile : true ,
gender : true
} )
. get ( ) ;
res . data [ 0 ] . last _login _ip = await obj . getIPAddress ( res . data [ 0 ] . last _login _ip ) ;
console . log ( res )
return {
code : 200 ,
data : res . data [ 0 ]
}
} catch ( e ) {
console . log ( e ) ;
return {
code : 500 ,
msg : e . message
}
}
}
}