diff --git a/src/ntqqapi/api/file.ts b/src/ntqqapi/api/file.ts
index 5f7dfe6..b233621 100644
--- a/src/ntqqapi/api/file.ts
+++ b/src/ntqqapi/api/file.ts
@@ -28,6 +28,7 @@ import { OnRichMediaDownloadCompleteParams } from '@/ntqqapi/listeners'
 import { Time } from 'cosmokit'
 
 export class NTQQFileApi {
+  /** 27187 TODO */
   static async getVideoUrl(peer: Peer, msgId: string, elementId: string) {
     const session = getSession()
     return (await session?.getRichMediaService().getVideoPlayUrlV2(peer,
diff --git a/src/ntqqapi/api/group.ts b/src/ntqqapi/api/group.ts
index f05d320..df028ea 100644
--- a/src/ntqqapi/api/group.ts
+++ b/src/ntqqapi/api/group.ts
@@ -1,6 +1,6 @@
 import { ReceiveCmdS } from '../hook'
 import { Group, GroupMember, GroupMemberRole, GroupNotifies, GroupRequestOperateTypes, GroupNotify } from '../types'
-import { invoke, NTMethod } from '../ntcall'
+import { invoke, NTClass, NTMethod } from '../ntcall'
 import { GeneralCallResult } from '../services'
 import { NTQQWindowApi, NTQQWindows } from './window'
 import { getSession } from '../wrapper'
@@ -10,18 +10,31 @@ import { NodeIKernelGroupService } from '../services'
 
 export class NTQQGroupApi {
   static async getGroups(forced = false): Promise<Group[]> {
-    type ListenerType = NodeIKernelGroupListener['onGroupListUpdate']
-    const [, , groupList] = await NTEventDispatch.CallNormalEvent
-      <(force: boolean) => Promise<any>, ListenerType>
-      (
-        'NodeIKernelGroupService/getGroupList',
-        'NodeIKernelGroupListener/onGroupListUpdate',
-        1,
-        5000,
-        () => true,
-        forced
-      )
-    return groupList
+    if (NTEventDispatch.initialised) {
+      type ListenerType = NodeIKernelGroupListener['onGroupListUpdate']
+      const [, , groupList] = await NTEventDispatch.CallNormalEvent
+        <(force: boolean) => Promise<any>, ListenerType>
+        (
+          'NodeIKernelGroupService/getGroupList',
+          'NodeIKernelGroupListener/onGroupListUpdate',
+          1,
+          5000,
+          () => true,
+          forced
+        )
+      return groupList
+    } else {
+      const result = await invoke<{
+        updateType: number
+        groupList: Group[]
+      }>({
+        className: NTClass.NODE_STORE_API,
+        methodName: 'getGroupList',
+        cbCmd: ReceiveCmdS.GROUPS_STORE,
+        afterFirstCmd: false,
+      })
+      return result.groupList
+    }
   }
 
   static async getGroupMembers(groupQQ: string, num = 3000): Promise<Map<string, GroupMember>> {
@@ -60,23 +73,8 @@ export class NTQQGroupApi {
     return result.result.infos
   }
 
-  static async getGroupNotifies() {
-    // 获取管理员变更
-    // 加群通知,退出通知,需要管理员权限
-    invoke<GeneralCallResult>({
-      methodName: ReceiveCmdS.GROUP_NOTIFY,
-      classNameIsRegister: true,
-    }).then()
-    return await invoke<GroupNotifies>({
-      methodName: NTMethod.GET_GROUP_NOTICE,
-      cbCmd: ReceiveCmdS.GROUP_NOTIFY,
-      afterFirstCmd: false,
-      args: [{ doubt: false, startSeq: '', number: 14 }, null],
-    })
-  }
-
   static async getGroupIgnoreNotifies() {
-    await NTQQGroupApi.getGroupNotifies()
+    await NTQQGroupApi.getSingleScreenNotifies(14)
     return await NTQQWindowApi.openWindow<GeneralCallResult & GroupNotifies>(
       NTQQWindows.GroupNotifyFilterWindow,
       [],
@@ -85,50 +83,86 @@ export class NTQQGroupApi {
   }
 
   static async getSingleScreenNotifies(num: number) {
-    const [_retData, _doubt, _seq, notifies] = await NTEventDispatch.CallNormalEvent
-      <(arg1: boolean, arg2: string, arg3: number) => Promise<any>, (doubt: boolean, seq: string, notifies: GroupNotify[]) => void>
-      (
-        'NodeIKernelGroupService/getSingleScreenNotifies',
-        'NodeIKernelGroupListener/onGroupSingleScreenNotifies',
-        1,
-        5000,
-        () => true,
-        false,
-        '',
-        num,
-      )
-    return notifies
+    if (NTEventDispatch.initialised) {
+      const [_retData, _doubt, _seq, notifies] = await NTEventDispatch.CallNormalEvent
+        <(arg1: boolean, arg2: string, arg3: number) => Promise<any>, (doubt: boolean, seq: string, notifies: GroupNotify[]) => void>
+        (
+          'NodeIKernelGroupService/getSingleScreenNotifies',
+          'NodeIKernelGroupListener/onGroupSingleScreenNotifies',
+          1,
+          5000,
+          () => true,
+          false,
+          '',
+          num,
+        )
+      return notifies
+    } else {
+      return await invoke<GroupNotifies>({
+        methodName: NTMethod.GET_GROUP_NOTICE,
+        cbCmd: ReceiveCmdS.GROUP_NOTIFY,
+        afterFirstCmd: false,
+        args: [{ doubt: false, startSeq: '', number: num }, null],
+      })
+    }
   }
 
+  /** 27187 TODO */
   static async delGroupFile(groupCode: string, files: string[]) {
     const session = getSession()
     return session?.getRichMediaService().deleteGroupFile(groupCode, [102], files)!
   }
 
-  static DelGroupFile = NTQQGroupApi.delGroupFile
-
   static async handleGroupRequest(flag: string, operateType: GroupRequestOperateTypes, reason?: string) {
     const flagitem = flag.split('|')
     const groupCode = flagitem[0]
     const seq = flagitem[1]
     const type = parseInt(flagitem[2])
     const session = getSession()
-    return session?.getGroupService().operateSysNotify(
-      false,
-      {
-        'operateType': operateType, // 2 拒绝
-        'targetMsg': {
-          'seq': seq,  // 通知序列号
-          'type': type,
-          'groupCode': groupCode,
-          'postscript': reason || ' ' // 仅传空值可能导致处理失败,故默认给个空格
-        }
+    if (session) {
+      return session.getGroupService().operateSysNotify(
+        false,
+        {
+          'operateType': operateType, // 2 拒绝
+          'targetMsg': {
+            'seq': seq,  // 通知序列号
+            'type': type,
+            'groupCode': groupCode,
+            'postscript': reason || ' ' // 仅传空值可能导致处理失败,故默认给个空格
+          }
+        })
+    } else {
+      return await invoke({
+        methodName: NTMethod.HANDLE_GROUP_REQUEST,
+        args: [
+          {
+            doubt: false,
+            operateMsg: {
+              operateType,
+              targetMsg: {
+                seq,
+                type,
+                groupCode,
+                postscript: reason || ' ' // 仅传空值可能导致处理失败,故默认给个空格
+              },
+            },
+          },
+          null,
+        ],
       })
+    }
   }
 
   static async quitGroup(groupQQ: string) {
     const session = getSession()
-    return session?.getGroupService().quitGroup(groupQQ)
+    if (session) {
+      return session.getGroupService().quitGroup(groupQQ)
+    } else {
+      return await invoke({
+        methodName: NTMethod.QUIT_GROUP,
+        args: [{ groupCode: groupQQ }, null],
+      })
+    }
   }
 
   static async kickMember(
@@ -138,33 +172,113 @@ export class NTQQGroupApi {
     kickReason = '',
   ) {
     const session = getSession()
-    return session?.getGroupService().kickMember(groupQQ, kickUids, refuseForever, kickReason)
+    if (session) {
+      return session.getGroupService().kickMember(groupQQ, kickUids, refuseForever, kickReason)
+    } else {
+      return await invoke({
+        methodName: NTMethod.KICK_MEMBER,
+        args: [
+          {
+            groupCode: groupQQ,
+            kickUids,
+            refuseForever,
+            kickReason,
+          },
+        ],
+      })
+    }
   }
 
   static async banMember(groupQQ: string, memList: Array<{ uid: string, timeStamp: number }>) {
     // timeStamp为秒数, 0为解除禁言
     const session = getSession()
-    return session?.getGroupService().setMemberShutUp(groupQQ, memList)
+    if (session) {
+      return session.getGroupService().setMemberShutUp(groupQQ, memList)
+    } else {
+      return await invoke({
+        methodName: NTMethod.MUTE_MEMBER,
+        args: [
+          {
+            groupCode: groupQQ,
+            memList,
+          },
+        ],
+      })
+    }
   }
 
   static async banGroup(groupQQ: string, shutUp: boolean) {
     const session = getSession()
-    return session?.getGroupService().setGroupShutUp(groupQQ, shutUp)
+    if (session) {
+      return session.getGroupService().setGroupShutUp(groupQQ, shutUp)
+    } else {
+      return await invoke({
+        methodName: NTMethod.MUTE_GROUP,
+        args: [
+          {
+            groupCode: groupQQ,
+            shutUp,
+          },
+          null,
+        ],
+      })
+    }
   }
 
   static async setMemberCard(groupQQ: string, memberUid: string, cardName: string) {
     const session = getSession()
-    return session?.getGroupService().modifyMemberCardName(groupQQ, memberUid, cardName)
+    if (session) {
+      return session.getGroupService().modifyMemberCardName(groupQQ, memberUid, cardName)
+    } else {
+      return await invoke({
+        methodName: NTMethod.SET_MEMBER_CARD,
+        args: [
+          {
+            groupCode: groupQQ,
+            uid: memberUid,
+            cardName,
+          },
+          null,
+        ],
+      })
+    }
   }
 
   static async setMemberRole(groupQQ: string, memberUid: string, role: GroupMemberRole) {
     const session = getSession()
-    return session?.getGroupService().modifyMemberRole(groupQQ, memberUid, role)
+    if (session) {
+      return session.getGroupService().modifyMemberRole(groupQQ, memberUid, role)
+    } else {
+      return await invoke({
+        methodName: NTMethod.SET_MEMBER_ROLE,
+        args: [
+          {
+            groupCode: groupQQ,
+            uid: memberUid,
+            role,
+          },
+          null,
+        ],
+      })
+    }
   }
 
   static async setGroupName(groupQQ: string, groupName: string) {
     const session = getSession()
-    return session?.getGroupService().modifyGroupName(groupQQ, groupName, false)
+    if (session) {
+      return session.getGroupService().modifyGroupName(groupQQ, groupName, false)
+    } else {
+      return await invoke({
+        methodName: NTMethod.SET_GROUP_NAME,
+        args: [
+          {
+            groupCode: groupQQ,
+            groupName,
+          },
+          null,
+        ],
+      })
+    }
   }
 
   static async getGroupAtAllRemainCount(groupCode: string) {
@@ -189,6 +303,7 @@ export class NTQQGroupApi {
     })
   }
 
+  /** 27187 TODO */
   static async removeGroupEssence(GroupCode: string, msgId: string) {
     const session = getSession()
     // 代码没测过
@@ -203,6 +318,7 @@ export class NTQQGroupApi {
     return session?.getGroupService().removeGroupEssence(param)
   }
 
+  /** 27187 TODO */
   static async addGroupEssence(GroupCode: string, msgId: string) {
     const session = getSession()
     // 代码没测过
diff --git a/src/ntqqapi/ntcall.ts b/src/ntqqapi/ntcall.ts
index 168f3e2..8f4781a 100644
--- a/src/ntqqapi/ntcall.ts
+++ b/src/ntqqapi/ntcall.ts
@@ -118,63 +118,57 @@ export function invoke<ReturnType>(params: InvokeParams<ReturnType>) {
   }
   const apiArgs = [params.methodName, ...(params.args ?? [])]
   //log('callNTQQApi', channel, eventName, apiArgs, uuid)
-  return new Promise((resolve: (data: ReturnType) => void, reject) => {
-    let success = false
-    if (!params.cbCmd) {
-      // QQ后端会返回结果,并且可以根据uuid识别
-      hookApiCallbacks[uuid] = (r: ReturnType) => {
-        success = true
-        resolve(r)
+  return Promise.race([
+    new Promise<ReturnType>((_, reject) => setTimeout(() => {
+      log(`ntqq api timeout ${channel}, ${eventName}, ${params.methodName}`, apiArgs)
+      reject(`ntqq api timeout ${channel}, ${eventName}, ${params.methodName}, ${apiArgs}`)
+    }, timeout)),
+    new Promise<ReturnType>((resolve: (data: ReturnType) => void, reject) => {
+      if (!params.cbCmd) {
+        // QQ后端会返回结果,并且可以根据uuid识别
+        hookApiCallbacks[uuid] = (r: ReturnType) => {
+          resolve(r)
+        }
       }
-    }
-    else {
-      // 这里的callback比较特殊,QQ后端先返回是否调用成功,再返回一条结果数据
-      const secondCallback = () => {
-        const hookId = registerReceiveHook<ReturnType>(params.cbCmd!, (payload) => {
-          // log(methodName, "second callback", cbCmd, payload, cmdCB);
-          if (!!params.cmdCB) {
-            if (params.cmdCB(payload)) {
+      else {
+        // 这里的callback比较特殊,QQ后端先返回是否调用成功,再返回一条结果数据
+        const secondCallback = () => {
+          const hookId = registerReceiveHook<ReturnType>(params.cbCmd!, (payload) => {
+            // log(methodName, "second callback", cbCmd, payload, cmdCB);
+            if (!!params.cmdCB) {
+              if (params.cmdCB(payload)) {
+                removeReceiveHook(hookId)
+                resolve(payload)
+              }
+            }
+            else {
               removeReceiveHook(hookId)
-              success = true
               resolve(payload)
             }
+          })
+        }
+        !afterFirstCmd && secondCallback()
+        hookApiCallbacks[uuid] = (result: GeneralCallResult) => {
+          log(`${params.methodName} callback`, result)
+          if (result?.result === 0 || result === undefined) {
+            afterFirstCmd && secondCallback()
           }
           else {
-            removeReceiveHook(hookId)
-            success = true
-            resolve(payload)
+            reject(`ntqq api call failed, ${result.errMsg}`)
           }
-        })
-      }
-      !afterFirstCmd && secondCallback()
-      hookApiCallbacks[uuid] = (result: GeneralCallResult) => {
-        log(`${params.methodName} callback`, result)
-        if (result?.result === 0 || result === undefined) {
-          afterFirstCmd && secondCallback()
-        }
-        else {
-          success = true
-          reject(`ntqq api call failed, ${result.errMsg}`)
         }
       }
-    }
-    setTimeout(() => {
-      if (!success) {
-        log(`ntqq api timeout ${channel}, ${eventName}, ${params.methodName}`, apiArgs)
-        reject(`ntqq api timeout ${channel}, ${eventName}, ${params.methodName}, ${apiArgs}`)
-      }
-    }, timeout)
-
-    ipcMain.emit(
-      channel,
-      {
-        sender: {
-          send: (..._args: unknown[]) => {
+      ipcMain.emit(
+        channel,
+        {
+          sender: {
+            send: (..._args: unknown[]) => {
+            },
           },
         },
-      },
-      { type: 'request', callbackId: uuid, eventName },
-      apiArgs,
-    )
-  })
+        { type: 'request', callbackId: uuid, eventName },
+        apiArgs,
+      )
+    })
+  ])
 }
\ No newline at end of file