Python sanic框架钉钉和第三方打卡机实现

同样还是需要开通钉钉应用这里就不错多说了

第一步:梳理逻辑流程

        前提:打卡的机器是使用postgres数据库,由于因为某些原因,钉钉userId 我已经提前获取到了存放到数据库里。

        1.用户打卡成功后,我们应该监听数据库进行查询,然后获取到打卡的时间,在通过钉钉的工作消息接口,发送消息给当前考勤打卡的用户,这样用户就可以知道我上班的打卡时间!

现在我们看看应该怎么去实现

先定义钉钉接口先Token:

appkey = ""
appsecret = ""
ding_url = "https://oapi.dingtalk.com/"


async def dingTalkToken():
    async with httpx.AsyncClient() as client:
        response = await client.get(ding_url + 'gettoken', params={"appkey": appkey, "appsecret": appsecret})

    # 解析响应JSON
    result = response.json()

    # 提取Access Token
    access_token = result.get("access_token")
    return access_token

钉钉工作消息接口

async def dingTalkTokenAsyncsend_v2(access_token, kqTime, userid):
    params = {
        "agent_id": ,
        "msg": {
            "msgtype": "text",
            "text": {
                "content": "打卡成功:" + kqTime
            }
        },
        "userid_list": userid
    }

    async with httpx.AsyncClient() as client:
        response = await client.post(
            ding_url + 'topapi/message/corpconversation/asyncsend_v2?access_token=' + access_token, params=params)

    # 解析响应JSON
    result = response.json()

    # 提取Access Token
    errcode = result.get("errcode")
    return errcode

以上向钉钉工作发送消息的接口已经完成了

接下来就是核心代码:

async def check_notifications():
    print('执行')
    try:
        # 连接到数据库
        with psycopg2.connect(dbname=posql.dbname, user=posql.user, password=posql.password, host=posql.host,
                              port=posql.port) as connection:
            # 创建一个游标对象,用于执行 SQL 语句
            with connection.cursor() as cursor:
                # 执行查询
                cursor.execute("LISTEN punch_event_channel")

                while True:
                    connection.commit()  # 提交事务
                    await asyncio.sleep(1)
                    # 检查是否有通知
                    connection.poll()  # 从服务器获取通知
                    if connection.notifies:
                        notify = connection.notifies[0]
                        # 执行查询
                        cursor.execute("这填写打卡系统的数据库使用ID去查询最新
SELECT * FROM table WHERE id = %s" % int(notify.payload))
                        # 获取查询结果
                        result = cursor.fetchone()
                        columns = [desc[0] for desc in cursor.description]
                        result_dict = dict(zip(columns, result))
                        # 处理 datetime 对象的序列化
                        result_dict['timestamp'] = result_dict.get('timestamp', None)
                        if result_dict['timestamp']:
                            result_dict['timestamp'] = datetime.fromisoformat(result_dict['timestamp'])
                        kqTime = result_dict['att_date'] + ' ' + result_dict['att_time']
                        # 获取用户ID
                        user_name = result_dict['person_name']
                        sql_str = """EXEC GetUserDingByName @UserName = N'%s';""" % user_name
                        user_id = query_user_info(sql_str)
                        if user_id != 'null':
                            # 发送HTTP POST请求获取Access Token
                            access_token = await dingTalkToken()
                            codes = await dingTalkTokenAsyncsend_v2(access_token, kqTime, user_id)
                            print(f"考勤时间: " + result_dict['att_date'] + ' ' + result_dict['att_time'])
                            break
                        else:
                            break

                        # 去执行 钉钉推送模块
                        # messages = '发送成功'
                    else:
                        print({"notify_payload": '没有消息'})
                        await asyncio.sleep(1)

    except Exception as e:
        print({"error": str(e)})

解释一下代码:

 # 执行查询
cursor.execute("LISTEN punch_event_channel")

这里我是在考勤机器的数据库里做了一个punch_event_channel 的频道,而这个频道是我创建了一个触发函数用来触发最新数据库里的数据

接下来是创建触发函数

-- 创建触发器函数
CREATE OR REPLACE FUNCTION notify_punch_event()
RETURNS TRIGGER AS
$$
BEGIN
    PERFORM pg_notify('punch_event_channel', 'new_punch_event');
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- 创建触发器,关联到表的 AFTER INSERT 事件上

CREATE TRIGGER 触发器名称XXXXX
AFTER INSERT ON 表名
FOR EACH ROW 
EXECUTE PROCEDURE notify_punch_event();

在sql 工具执行这两句就可以了,替换成你自己的数据库

另外这里是我内部拿取钉钉Userid的数据库,我就不放代码了:

# 获取用户ID
user_name = result_dict['person_name']
sql_str = """EXEC GetUserDingByName @UserName = N'%s';""" % user_name
user_id = query_user_info(sql_str)

你们可以根据自己方式,来获取

最后,就是使用定时任务来

async def periodic_task():
    while True:
        await check_notifications()

        await asyncio.sleep(1)  # 1秒钟检查一次,可以根据需要调整间隔


if __name__ == '__main__':
    # 启动定时任务
    app.add_task(periodic_task())

    # 启动 Sanic 应用
    app.run(host='0.0.0.0', port=8089, workers=8)

最后记得导入包

import psycopg2
import httpx
import pymssql # 这是sql server 数据库连接

如果写的好动动你们发财的小手点赞,对你有帮助也可以打赏请我喝杯咖啡,提提神,感谢各位兄弟了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/274999.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

西北大学844计算机类考研-25级初试高分总攻略

西北大学844计算机类考研-25级初试高分攻略 个人介绍 ​ 本人是西北大学22级软件工程研究生,考研专业课129分,过去一年里在各大辅导机构任职,辅导考研学生专业课844,辅导总时长达400小时,辅导学生超过20余人&#xf…

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之线性布局容器Row组件

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之线性布局容器Row组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、Row组件 沿水平方向布局容器。 子组件 可以包含子组件。 接口 Row(…

【SVN】Windows版合并提交bat文件+自定义菜单快捷键

【工具向】利用bat批处理打开TortoiseGit简化版本管理流程_tortoisegit bat-CSDN博客 start cmd /k "cd C:\YourBranchProj && svn cleanup && svn update && svn merge C:\YourTrunkProj -r 历史版本号:HEAD && svn commit -m "me…

pyCharm 打印控制台中文乱码解决办法

解决方法 在 "File" -> "Settings" 中的控制台设置: 在 "File" -> "Settings" 中,你可以找到 "Editor" -> "General" -> "Console"。在这里,你可能会找到…

数据结构:栈

1.栈的定义 栈是仅限在表尾进行插入和删除的线性表,栈又被称为后进先出的线性表 1.1栈顶和栈底 栈是一个线性表,我们允许插入和删除的一端称为栈顶 栈底和栈顶相对,实际上栈底的元素不需要关心 1.2入栈和出栈 栈元素的插入操作叫做入栈&…

“2023年的技术发展与个人成长:回顾与展望“

文章目录 每日一句正能量前言工作生活未来展望后记 每日一句正能量 凡事顺其自然,遇事处于泰然,得意之时淡然,失意之时坦然,艰辛曲折必然,历尽沧桑悟然。 前言 在这快速发展的信息时代,技术的进步和创新不…

vue2中使用百度地图BMapGL

1、npm 命令安装 npm install vue-bmap-gl --save2、main.js 中文件引入 import VueBMap from vue-bmap-gl import vue-bmap-gl/dist/style.css VueBMap.initBMapApiLoader({// 百度的keyak:*********,// 这个密钥请使用自己注册的 }) Vue.use(VueBMap)3、页面调用 <temp…

Python 中的数学运算(Python Math)

Python中的math模块是数学运算的重要工具&#xff0c;提供了丰富的数学函数和常数。本文将深入探讨math模块的功能和用法&#xff0c;使您能够更好地利用Python进行数学运算。 Python的math模块是一个强大的工具集&#xff0c;涵盖了许多基本的数学函数和常数&#xff0c;适用…

C++11 lambda函数和包装器

目录 前言 一.lambda的引入 二、lambda函数的使用 1.一般使用 2.引用 三、包装器 1.包装普通对象 2.包装类成员对象 3.bind 前言 学习过python的同学应该对lambda函数不陌生&#xff0c;这是一个匿名函数&#xff0c;不需要写函数的名字。在不会多地方调用某个简单函数…

kubeadm来搭建k8s集群。

我们采用了二进制包搭建出的k8s集群&#xff0c;本次我们采用更为简单的kubeadm的方式来搭建k8s集群。 二进制的搭建更适合50台主机以上的大集群&#xff0c;kubeadm更适合中小型企业的集群搭建 主机配置建议&#xff1a;2c 4G 主机节点 IP …

ElementUI的Table组件行合并上手指南

ElementUI的Table组件行合并 &#xff0c;示例用官网vue3版的文档 <el-table :data"tableData" :span-method"objectSpanMethod" border style"width: 100%; margin-top: 20px"><el-table-column prop"id" label"ID&qu…

全面解析 I2C 通信协议

全面解析 I2C 通信协议 lvy 嵌入式学习规划 2023-12-22 21:20 发表于陕西 嵌入式学习规划 嵌入式软件、C语言、ARM、Linux、内核、驱动、操作系统 80篇原创内容 公众号 点击左上方蓝色“嵌入式学习规划”&#xff0c;选择“设为星标” 1、什么是I2C协议 I2C 协议是一个允许…

postman使用-03发送请求

文章目录 请求1.新建请求2.选择请求方式3.填写请求URL4.填写请求参数get请求参数在params中填写&#xff08;填完后在url中会自动显示&#xff09;post请求参数在body中填写&#xff0c;根据接口文档请求头里面的content-type选择body中的数据类型post请求参数为json-选择raw-选…

高压放大器的使用方法是什么

高压放大器是一种重要的电子设备&#xff0c;其主要功能是放大输入信号的电压&#xff0c;并输出更高电压的信号。它在各种工业、实验室和研究领域都有着广泛的应用。下面安泰电子官网将详细介绍高压放大器的使用方法以及相关注意事项。 高压放大器是一种专门用于将低电压信号转…

Unity is running with Administrator privileges, which is not supported

Unity is running with Administrator privileges, which is not supported 如果还是弹出CMD窗口提示输入密码&#xff0c;但无法怎样都无法输入&#xff0c;请关闭窗口&#xff0c;然后右键快捷方式管理员运行一次。 ----------分割线---------- 为什么这样做&#xff1f; 很…

模型量化 | Pytorch的模型量化基础

官方网站&#xff1a;Quantization — PyTorch 2.1 documentation Practical Quantization in PyTorch | PyTorch 量化简介 量化是指执行计算和存储的技术 位宽低于浮点精度的张量。量化模型 在张量上执行部分或全部操作&#xff0c;精度降低&#xff0c;而不是 全精度&#xf…

多线程编程(二)信号量

上边的函数是获取资源&#xff0c;下边的函数是释放资源。信号量就是当有多个线程争夺共享资源的时候信号量相当于管控的&#xff0c;57个人去50个位置的餐厅吃饭&#xff0c;信号量是管理开关门的呢个。 QSemaphore freesapce(buffersize);//缓冲区大小。 QSemaphore usedsp…

Oracle数据updater如何回滚

1.查询update语句执行的时间节点 &#xff1b; select t.FIRST_LOAD_TIME, t.SQL_TEXT from v$sqlarea t where to_char(t.FIRST_LOAD_TIME) > 2023-03-19/17:00:00 order by t.FIRST_LOAD_TIME desc;开启表的行迁移 alter table test enable row movement;3.回滚表数据到…

uni-app/vue封装etc车牌照输入,获取键盘按键键值

先看下效果如下&#xff1a; 动态图如下 uniapp的keyup获取不到keyCode和compositionstart&#xff0c;compositionend&#xff0c;所以需要监听input节点的keyup事件&#xff0c; 思路以及代码如下&#xff1a; 1.将每一个字符用文本框输入&#xff0c;代码如下 <view …

volatile关键字的作用是什么?

大家好&#xff0c;我是"java继父"伯约&#xff0c;这篇对大家有帮助的话求一个赞&#xff0c;另外文章末尾放了我从月入7k到现在3W的学习资料&#xff0c;大家可以去领一下&#xff08;无偿&#xff09;。 1.防重排序 我们从一个最经典的例子来分析重排序问题。大家…