Example #1
0
def get_setu_native(uid=0):
    image = generate_image_struct()

    path = f'setu_mix/acggov'
    res = R.img(path)
    if not os.path.exists(res.path):
        return image

    if uid == 0:
        fn = random.choice(os.listdir(res.path))
        if fn.split('.')[0].isdigit():
            uid = int(fn.split('.')[0])

    if not uid:
        return image

    image['id'] = int(uid)
    image['native'] = True

    path = f'setu_mix/acggov/{uid}'
    res = R.img(path)
    try:
        image['data'] = res.path + '.jpg'
        with open(res.path + '.json', encoding='utf8') as f:
            d = json.load(f)
            for k, v in d.items():
                image[k] = v
    except:
        pass

    return image
Example #2
0
 def card(self):
     res = R.img(f'priconne/card/card_{self.id}61.png')
     if not res.exist:
         res = R.img(f'priconne/card/card_{self.id}31.png')
     if not res.exist:
         res = R.img(f'priconne/unit/icon_unit_{UNKNOWN}31.png')
     return res
Example #3
0
async def img(bot, ev, msg, uid):

    image_path = R.img(f'image-generate/image/{uid}.jpg').path
    if os.path.exists(image_path):
        os.remove(image_path)
    file = await get.getQqName(uid)
    color = await get.getIni(file,"color")
    ini = str(await get.getIni(file,"name"))
    image_path_new = R.img(f'image-generate/image_data/{file}/{ini}.jpg').path

    img = Image.open(image_path_new)
    draw = ImageDraw.Draw(img)
    font_size=await get.getIni(file,"font_size")
    font_max=await get.getIni(file,"font_max")
    image_font_center=(await get.getIni(file,"font_center_x"),await get.getIni(file,"font_center_y"))
    image_font_sub = await get.getIni(file,"font_sub")
    ttfront = ImageFont.truetype(os.path.join(os.path.dirname(__file__), 'simhei.ttf'),font_size)  # 设置字体暨字号
    font_length = ttfront.getsize(msg)
    #print(font_length)
    while font_length[0]>font_max:
        font_size-=image_font_sub
        ttfront = ImageFont.truetype(os.path.join(os.path.dirname(__file__), 'simhei.ttf'), font_size)
        font_length = ttfront.getsize(msg)
    #print(ttfront.getsize("你好"))
    # 自定义打印的文字和文字的位置
    if font_length[0]>5:
        draw.text((image_font_center[0]-font_length[0]/2, image_font_center[1]-font_length[1]/2),
                    msg, fill=color,font=ttfront)
        img.save(image_path)
        await bot.send(ev, R.img(f'image-generate/image/{uid}.jpg').cqcode, at_sender=True)
Example #4
0
def icon(num, types):
    res = R.img(f'priconne/{types}/icon_{types}_{num}.png')
    if not res.exist:
        download_icon(num, types)
        res = R.img(f'priconne/{types}/icon_{types}_{num}.png')
    if not res.exist:
        res = R.img(f'priconne/unit/icon_unit_{UNKNOWN}31.png')
    return res
Example #5
0
def get_nv_icon(cid):
    c = chara.fromid(cid)
    mes = c.icon.cqcode
    PIC_PATH = R.img('dlc/full').path
    path = os.path.join(PIC_PATH, f'{cid}31.png')
    if os.path.exists(path):
        mes = str(R.img(f'dlc/full/{cid}31.png').cqcode)
    return mes
Example #6
0
async def rank_sheet(bot, ev):
    match = ev['match']
    is_jp = match.group(2) == '日'
    is_tw = match.group(2) == '台'
    is_cn = match.group(2) and match.group(2) in '国陆b'
    if not is_jp and not is_tw and not is_cn:
        await bot.send(ev,
                       '\n请问您要查询哪个服务器的rank表?\n*日rank表\n*台rank表\n*陆rank表',
                       at_sender=True)
        return
    msg = [
        '\n※表格仅供参考,升r有风险,强化需谨慎\n※一切以会长要求为准——',
    ]
    if is_jp:
        flist = get_rank_pic('jp')
        if len(flist) == 0:
            await bot.send(ev, '无数据', at_sender=True)
            return
        args = re.split(r'\.|-', flist[0])
        msg.append(
            f'※不定期搬运自图中Q群\n※广告为原作者推广,与本bot无关\n{args[0]}-{args[1]} rank表:')
        pos = match.group(3)
        if not pos or '前' in pos:
            p = R.img('priconne/quick/' + flist[0]).cqcode
            msg.append(str(p))
        if len(flist) >= 2 and not pos or '中' in pos:
            p = R.img('priconne/quick/' + flist[1]).cqcode
            msg.append(str(p))
        if len(flist) >= 3 and not pos or '后' in pos:
            p = R.img('priconne/quick/' + flist[2]).cqcode
            msg.append(str(p))
        await bot.send(ev, '\n'.join(msg), at_sender=True)
        await util.silence(ev, 60)
    elif is_tw:
        flist = get_rank_pic('tw')
        if len(flist) == 0:
            await bot.send(ev, '无数据', at_sender=True)
            return
        args = re.split(r'\.|-', flist[0])
        msg.append(f'※不定期搬运自漪夢奈特\n※油管频道有介绍视频及原文档\n{args[0]}-{args[1]} rank表:')
        for fn in flist:
            p = R.img('priconne/quick/' + fn).cqcode
            msg.append(f'{p}')
        await bot.send(ev, '\n'.join(msg), at_sender=True)
        await util.silence(ev, 60)
    elif is_cn:
        flist = get_rank_pic('cn')
        if len(flist) == 0:
            await bot.send(ev, '无数据', at_sender=True)
            return
        args = re.split(r'\.|-', flist[0])
        msg.append(f'※不定期搬运自NGA\n{args[0]}-{args[1]} rank表:')
        for fn in flist:
            p = R.img('priconne/quick/' + fn).cqcode
            msg.append(f'{p}')
        await bot.send(ev, '\n'.join(msg), at_sender=True)
        await util.silence(ev, 60)
Example #7
0
 def icon(self):
     res = R.img(f'dlc/icon/icon_unit_{self.id}61.png')
     if not res.exist:
         res = R.img(f'dlc/icon/icon_unit_{self.id}31.png')
     if not res.exist:
         res = R.img(f'dlc/icon/icon_unit_{self.id}11.png')
     if not res.exist:
         res = R.img(f'dlc/icon/icon_unit_{UNKNOWN}31.png')
     return res
Example #8
0
async def hour_call():
    now = datetime.now(tz)
    if 2 <= now.hour <= 4:
        return  # 宵禁 免打扰
    msg = get_hour_call()[now.hour]
    if (msg == 'maiyao'):
        pic = R.img('biaoqing/maiyao.jpg').cqcode
        await sv.broadcast(f'{pic}', 'hourcall', 0)
    elif (msg == 'shuijiao'):
        pic = R.img('biaoqing/shuijiao.jpg').cqcode
        await sv.broadcast(f'{pic}', 'hourcall', 0)
Example #9
0
def pic_gender_cqcode(dic_name):
    '''
    获得/res/img/dic_name目录下一张随机图片,返回cqcode
    '''
    pic_dir = R.img(dic_name).path
    
    file_list:list = os.listdir(pic_dir)
    img_random = random.choice(file_list)
    img_path = dic_name + '/' + img_random
    img_cqcode = R.img(str(img_path)).cqcode
    return img_cqcode
Example #10
0
def get_tiangou_pic():
    path = f'anti-holo'
    res = R.img(path)
    if not os.path.exists(res.path):
        return get_origin_tiangou_pic()
    fnlist = os.listdir(res.path)
    if len(fnlist) == 0:
        return get_origin_tiangou_pic()
    fn = random.choice(fnlist)
    path = f'anti-holo/' + fn
    return R.img(path)
Example #11
0
async def who_is_longwang(bot, ev):
    gid = ev.group_id
    img_path = R.img('longwang/').path
    data = await bot.get_group_honor_info(group_id=gid, type='talkative')
    talkative = data['current_talkative']
    uid = talkative['user_id']
    files = os.listdir(img_path)
    filename = random.choice(files)
    img = R.img('longwang/', filename)
    at = MessageSegment.at(uid)
    msg = f'{at}\n{img.cqcode}'
    await bot.send(ev, msg)
Example #12
0
def drawing_pic(model) -> Image:
    fontPath = {
        'title': R.img('genshintunedata/font/Mamelon.otf').path,
        'text': R.img('genshintunedata/font/sakura.ttf').path
    }

    if model == 'KELI':
        base_img = get_base_by_name("frame_1.png")
    elif model == 'TWINS':
        base_img = get_base_by_name('frame_42.png')
    else:
        base_img = random_Basemap()

    filename = os.path.basename(base_img.path)
    charaid = filename.lstrip('frame_')
    charaid = charaid.rstrip('.png')

    img = base_img.open()
    # Draw title
    draw = ImageDraw.Draw(img)
    text, title = get_info(charaid)

    text = text['content']
    font_size = 45
    color = '#F5F5F5'
    image_font_center = (140, 99)
    ttfront = ImageFont.truetype(fontPath['title'], font_size)
    font_length = ttfront.getsize(title)
    draw.text((image_font_center[0] - font_length[0] / 2,
               image_font_center[1] - font_length[1] / 2),
              title,
              fill=color,
              font=ttfront)
    # Text rendering
    font_size = 25
    color = '#323232'
    image_font_center = [140, 297]
    ttfront = ImageFont.truetype(fontPath['text'], font_size)
    result = decrement(text)
    if not result[0]:
        return Exception('Unknown error in daily luck')
    textVertical = []
    for i in range(0, result[0]):
        font_height = len(result[i + 1]) * (font_size + 4)
        textVertical = vertical(result[i + 1])
        x = int(image_font_center[0] + (result[0] - 2) * font_size / 2 +
                (result[0] - 1) * 4 - i * (font_size + 4))
        y = int(image_font_center[1] - font_height / 2)
        draw.text((x, y), textVertical, fill=color, font=ttfront)

    img = pic2b64(img)
    img = MessageSegment.image(img)
    return img
Example #13
0
def drawing(model, userQQ):
    RESOURCES_BASE_PATH = data[model.value[0]]
    fontPath = {
        "title": f"{RESOURCES_BASE_PATH}/font/Mamelon.otf",
        "text": f"{RESOURCES_BASE_PATH}/font/sakura.ttf",
    }
    if model.value[1] != "default":
        imgPath = f"{RESOURCES_BASE_PATH}/img/frame_{model.value[1]}.jpg"
    else:
        imgPath = randomBasemap(RESOURCES_BASE_PATH)

    img = Image.open(imgPath)
    # Draw title
    text = copywriting(RESOURCES_BASE_PATH)
    title = getTitle(text, RESOURCES_BASE_PATH)
    text = text["content"]
    gen_path = hash(imgPath + title + text)
    if R.img(f'chouqian/{gen_path}.jpg').exist:
        return R.img(f'chouqian/{gen_path}.jpg').cqcode

    draw = ImageDraw.Draw(img)
    font_size = 45
    color = "#F5F5F5"
    image_font_center = (140, 99)
    ttfront = ImageFont.truetype(fontPath["title"], font_size)
    font_length = ttfront.getsize(title)
    draw.text(
        (
            image_font_center[0] - font_length[0] / 2,
            image_font_center[1] - font_length[1] / 2,
        ),
        title,
        fill=color,
        font=ttfront,
    )
    # Text rendering
    font_size = 25
    color = "#323232"
    image_font_center = [140, 297]
    ttfront = ImageFont.truetype(fontPath["text"], font_size)
    result = decrement(text)
    for i in range(0, result[0]):
        font_height = len(result[i + 1]) * (font_size + 4)
        textVertical = vertical(result[i + 1])
        x = int(image_font_center[0] + (result[0] - 2) * font_size / 2 +
                (result[0] - 1) * 4 - i * (font_size + 4))
        y = int(image_font_center[1] - font_height / 2)
        draw.text((x, y), textVertical, fill=color, font=ttfront)
    # Save
    img.save(R.img(f'chouqian/{gen_path}.jpg').path)
    return R.img(f'chouqian/{gen_path}.jpg').cqcode
Example #14
0
async def zhu(bot, ev):
    response = req.get(getzhuImg(sethtml4()))
    ls_f = base64.b64encode(BytesIO(response.content).read())
    imgdata = base64.b64decode(ls_f)
    save_dir = R.img('destiny2').path
    path_dir = os.path.join(save_dir, 'zhuwang.jpg')
    file = open(path_dir, 'wb')
    file.write(imgdata)
    file.close()
    pzhuwang = ' '.join(map(str, [
        R.img(f'destiny2/zhuwang.jpg').cqcode,
    ]))
    msg = f'命运2 蛛王:\n图片来源:小黑盒百科\n注意小黑盒蛛王信息可能更新较慢\n{pzhuwang}'
    await bot.send(ev, msg)
Example #15
0
async def chall(bot, ev):
    response = req.get(getchallImg(sethtml3()))
    ls_f = base64.b64encode(BytesIO(response.content).read())
    imgdata = base64.b64decode(ls_f)
    save_dir = R.img('destiny2').path
    path_dir = os.path.join(save_dir, 'shilian.jpg')
    file = open(path_dir, 'wb')
    file.write(imgdata)
    file.close()
    pshilian = ' '.join(map(str, [
        R.img(f'destiny2/shilian.jpg').cqcode,
    ]))
    msg = f'命运2 试炼周报:\n图片作者:seanalpha\n{pshilian}'
    await bot.send(ev, msg)
Example #16
0
async def zhuwangreminder():
    sys.stdout.flush()
    response = req.get(getzhuImg(sethtml4()))
    ls_f = base64.b64encode(BytesIO(response.content).read())
    imgdata = base64.b64decode(ls_f)
    save_dir = R.img('destiny2').path
    path_dir = os.path.join(save_dir,'zhuwang.jpg')
    file = open(path_dir,'wb')
    file.write(imgdata)
    file.close()
    pzhuwang = ' '.join(map(str, [
        R.img(f'destiny2/zhuwang.jpg').cqcode,
    ]))
    msg = '今天是' + get_week_day(get_time()) + '\n蛛王商店已刷新\n注意小黑盒蛛王信息可能更新较慢\n' + f'命运2 蛛王:\n图片来源:小黑盒百科\n{pzhuwang}'
    await svzw.broadcast(msg, 'zhuwang-reminder', 0.2)
Example #17
0
async def buy(bot, ev):
    response = req.get(
        "https://cdn.jsdelivr.net/gh/azmiao/picture-bed/img/buy-13.jpg")
    ls_f = base64.b64encode(BytesIO(response.content).read())
    imgdata = base64.b64decode(ls_f)
    save_dir = R.img('destiny2').path
    path_dir = os.path.join(save_dir, 'guangchen.jpg')
    file = open(path_dir, 'wb')
    file.write(imgdata)
    file.close()
    pguangchen = ' '.join(map(str, [
        R.img(f'destiny2/guangchen.jpg').cqcode,
    ]))
    msg = f'命运2 第13赛季光尘商店:\n{pguangchen}'
    await bot.send(ev, msg)
Example #18
0
async def NvZhuang(bot: HoshinoBot, ev: CQEvent):
    groupid = ev.group_id
    groupid = str(groupid)
    imgs = os.listdir(R.img('NvZhuang/').path)
    img = R.img('NvZhuang/' + random.choice(imgs))
    at = MessageSegment.at(config[groupid]['QQ'])
    try:
        if config[groupid]['AT']:
            await bot.send(ev, f'{at}女装!\n{img.cqcode}')
        else:
            info = await bot.get_stranger_info(user_id=config[groupid]['QQ'], no_cache=True)
            nickname = info['nickname']
            await bot.send(ev, f'{nickname}女装!\n{img.cqcode}')
    except KeyError:
        await bot.send(ev, '请先设置迫害QQ')
Example #19
0
async def send_to_private(user_id: int, url: str, pid: str, p: str, title: str,
                          author: str, ori_url: str):
    msg = format_msg(url, pid, p, title, author, ori_url)
    await bot.send_private_msg(user_id=user_id, message=msg)
    filename = url.split('/')[-1]
    if not os.path.exists(R.img(f'setuweb/{filename}').path):
        await down_img(url)
    if config['antishielding']:
        path = R.img(f'setuweb/{filename}').path
        await imgAntiShielding(path)
        imgtype = path.split('.')[-1]
        imgname = path.split('\\')[-1].split('.')[-2]
        filename = f'{imgname}_anti.{imgtype}'
    img = R.img(f'setuweb/{filename}').cqcode
    await bot.send_private_msg(user_id=user_id, message=img)
Example #20
0
def setu_gener():
    while True:
        filelist = os.listdir(setu_folder)
        random.shuffle(filelist)
        for filename in filelist:
            if os.path.isfile(os.path.join(setu_folder, filename)):
                yield R.img('setu/', filename)
Example #21
0
async def zhoubaoreminder():
    sys.stdout.flush()
    if get_week_day(get_time()) == '星期三':
        response = req.get(getzhoubaoImg(sethtml1()))
        ls_f = base64.b64encode(BytesIO(response.content).read())
        imgdata = base64.b64decode(ls_f)
        save_dir = R.img('destiny2').path
        path_dir = os.path.join(save_dir,'zhoubao.jpg')
        file = open(path_dir,'wb')
        file.write(imgdata)
        file.close()
        pzhoubao = ' '.join(map(str, [
            R.img(f'destiny2/zhoubao.jpg').cqcode,
        ]))
        msg = '今天是' + get_week_day(get_time()) + '\n周报已更新\n' + f'命运2 周报:\n图片作者:seanalpha\n{pzhoubao}'
        await svzb.broadcast(msg, 'zhoubao-reminder', 0.2)
Example #22
0
def save_image(image, mode='acggov'):
    path = f'setu_mix/{mode}/{image["id"]}'

    res = R.img(path + '.jpg')
    with open(res.path, 'wb') as f:
        f.write(image['data'])

    res = R.img(path + '.json')
    info = {
        'title': image['title'],
        'author': image['author'],
        'url': image['url'],
        'tags': image['tags'],
    }
    with open(res.path, 'w', encoding='utf8') as f:
        json.dump(info, f, ensure_ascii=False, indent=2)
Example #23
0
async def search_setu_online(keyword, num):
    image_list = await query_search(keyword)
    valid_list = []
    while len(image_list) > 0:
        image = image_list.pop(random.randint(0, len(image_list) - 1))
        #检查本地是否存在该图片
        path = f'setu_mix/acggov/{image["id"]}.jpg'
        res = R.img(path)
        if os.path.exists(res.path):
            image['data'] = res.path
            image['native'] = True
        else:
            url = image['url']
            if get_config('acggov', 'pixiv_direct'):
                image['data'] = await download_pixiv_image(url, image['id'])
            else:
                url = url.replace("https://i.pximg.net", "https://i.pixiv.cat")
                image['data'] = await download_acggov_image(url)
            image['native'] = False
            if image['data']:
                if get_config('acggov', 'mode') == 2:
                    save_image(image)
                    image['data'] = res.path
        if image['data']:
            valid_list.append(image)
        if len(valid_list) >= num:
            break
    return valid_list
Example #24
0
async def pcr_reminder_potion():
    now = datetime.now(tz)
    if (now.hour not in list):
        return  # 宵禁 免打扰
    pic = R.img(f"potion{random.randint(1, 4)}.jpg").cqcode
    msg = f'{pic}'
    await svpotion.broadcast(msg, 'pcr-reminder-potion', 0)
Example #25
0
async def download_comic(id_):
    '''
    下载指定id的官方四格漫画,同时更新漫画目录index.json
    episode_num可能会小于id
    '''
    base = 'https://comic.priconne-redive.jp/api/detail/'
    save_dir = R.img('priconne/comic/').path
    index = load_index()

    # 先从api获取detail,其中包含图片真正的链接
    sv.logger.info(f'getting comic {id_} ...')
    url = base + id_
    sv.logger.info(f'url={url}')
    resp = await aiorequests.get(url)
    sv.logger.info(f'status_code={resp.status_code}')
    if 200 != resp.status_code:
        return
    data = await resp.json()
    data = data[0]

    episode = data['episode_num']
    title = data['title']
    link = data['cartoon']
    index[episode] = {'title': title, 'link': link}
    sv.logger.info(f'episode={index[episode]}')

    # 下载图片并保存
    await download_img(os.path.join(save_dir, get_pic_name(episode)), link)

    # 保存官漫目录信息
    with open(os.path.join(save_dir, 'index.json'), 'w', encoding='utf8') as f:
        json.dump(index, f, ensure_ascii=False)
Example #26
0
async def update_seeker():
    '''
    轮询官方四格漫画更新
    若有更新则推送至订阅群
    '''
    index_api = 'https://comic.priconne-redive.jp/api/index'
    index = load_index()

    # 获取最新漫画信息
    resp = await aiorequests.get(index_api, timeout=10)
    data = await resp.json()
    id_ = data['latest_cartoon']['id']
    episode = data['latest_cartoon']['episode_num']
    title = data['latest_cartoon']['title']

    # 检查是否已在目录中
    # 同一episode可能会被更新为另一张图片(官方修正),此时episode不变而id改变
    # 所以需要两步判断
    if episode in index:
        qs = urlparse(index[episode]['link']).query
        old_id = parse_qs(qs)['id'][0]
        if id_ == old_id:
            sv.logger.info('未检测到官漫更新')
            return

    # 确定已有更新,下载图片
    sv.logger.info(f'发现更新 id={id_}')
    await download_comic(id_)

    # 推送至各个订阅群
    pic = R.img('priconne/comic', get_pic_name(episode)).cqcode
    msg = f'プリンセスコネクト!Re:Dive公式4コマ更新!\n第{episode}話 {title}\n{pic}'
    await sv.broadcast(msg, 'PCR官方四格', 0.5)
Example #27
0
async def shilianreminder():
    sys.stdout.flush()
    if get_week_day(get_time()) == '星期六':
        response = req.get(getchallImg(sethtml3()))
        ls_f = base64.b64encode(BytesIO(response.content).read())
        imgdata = base64.b64decode(ls_f)
        save_dir = R.img('destiny2').path
        path_dir = os.path.join(save_dir,'shilian.jpg')
        file = open(path_dir,'wb')
        file.write(imgdata)
        file.close()
        pshilian = ' '.join(map(str, [
            R.img(f'destiny2/shilian.jpg').cqcode,
        ]))
        msg = '今天是' + get_week_day(get_time()) + '\n试炼周报已更新\n' + f'命运2 试炼周报:\n图片作者:seanalpha\n{pshilian}'
        await svsl.broadcast(msg, 'shilian-reminder', 0.2)
Example #28
0
async def laojiureminder():
    sys.stdout.flush()
    if get_week_day(get_time()) == '星期六':
        response = req.get(getxurImg(sethtml2()))
        ls_f = base64.b64encode(BytesIO(response.content).read())
        imgdata = base64.b64decode(ls_f)
        save_dir = R.img('destiny2').path
        path_dir = os.path.join(save_dir,'xur.jpg')
        file = open(path_dir,'wb')
        file.write(imgdata)
        file.close()
        pxur = ' '.join(map(str, [
            R.img(f'destiny2/xur.jpg').cqcode,
        ]))
        msg = '今天是' + get_week_day(get_time()) + '\n老九信息已更新\n' + f'命运2 仄:\n图片作者:seanalpha\n{pxur}'
        await svlj.broadcast(msg, 'laojiu-reminder', 0.2)
Example #29
0
async def get_setu_online(num, r18=0, keyword=None):
    image_list = await query_setu(r18=r18, keyword=keyword)
    if get_api_num() != 1:
        while image_list == None:
            image_list = await query_setu(r18=r18, keyword=keyword)
    else:
        if image_list == None:
            return
    valid_list = []

    while len(image_list) > 0:
        image = image_list.pop(random.randint(0, len(image_list) - 1))
        #检查本地是否存在该图片
        path = f'setu_mix/lolicon/{image["id"]}.jpg'
        if image['r18']:
            path = f'setu_mix/lolicon_r18/{image["id"]}.jpg'
        res = R.img(path)
        if os.path.exists(res.path):
            image['data'] = res.path
            image['native'] = True
        else:
            if get_config('lolicon', 'pixiv_direct'):
                image['data'] = await download_pixiv_image(
                    image['url'], image['id'])
            else:
                image['data'] = await download_image(image['url'])
            image['native'] = False
            if image['data'] and get_config('lolicon', 'mode') == 2:
                save_image(image)
                image['data'] = res.path
        if image['data']:
            valid_list.append(image)
        if len(valid_list) >= num:
            break
    return valid_list
Example #30
0
def gen_gif_response(ill_id):
    result = api.ugoira_metadata(ill_id)
    url = result.get('ugoira_metadata').get('zip_urls').get('medium')
    delay = result.get('ugoira_metadata').get('frames')[0].get('delay')
    fps = 1000 / delay
    zip_name = url[url.rfind("/") + 1:]
    name = zip_name.replace('.zip', '')
    path = R.img(f'ghs/gif/{name}').path
    gif_name = name + '.gif'
    target_name = R.img(f'ghs/gif/{gif_name}').path
    if not os.path.exists(target_name):
        api.download(url, path=R.img(f'ghs/gif').path, replace=True)
        unzip_single(R.img(f'ghs/gif/{zip_name}').path, path)
        filenames = sorted((os.path.join(path, fn) for fn in os.listdir(path)))
        package_2_gif(filenames, target_name, fps=fps)
    return str(R.img(f'ghs/gif/{gif_name}').cqcode)