Added Paydisini Integration (#309)

This commit is contained in:
Yasir Aris M 2024-09-14 13:03:34 +07:00 committed by GitHub
parent 638cde6dd7
commit 3f6cd58db2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 176 additions and 4 deletions

View file

@ -13,7 +13,7 @@ FROM yasirarism/misskaty-docker:py3.12
ENV HOSTNAME=yasir-server
# Copy Files
COPY . .
# Instal pip package
# Instal pip package if you use free depedencies
# RUN pip3 install --no-cache-dir -r requirements.txt
# Set CMD Bot
CMD ["bash", "start.sh"]

16
database/payment_db.py Normal file
View file

@ -0,0 +1,16 @@
from database import dbname
from typing import Optional
autopay = dbname["autpay"]
async def delete_autopay(uniqueCode: str):
await autopay.delete_one({"_id": uniqueCode})
async def get_autopay(self, uniqueCode: str):
exists = await autopay.find_one({"_id": uniqueCode})
return exists
async def autopay_update(self, msg_id: Optional[int] = "", note: Optional[str] = "", user_id: Optional[int] = "", amount: Optional[int] = "", status: Optional[str] = "", uniqueCode: Optional[str] = "", createdAt: Optional[str] = ""):
data = {"msg_id": msg_id, "note": note, "user_id": user_id, "amount": amount, "status": status, "createdAt": createdAt}
await autopay.update_one({"_id": uniqueCode}, {"$set": data}, upsert=True)

View file

@ -8,12 +8,13 @@ from asyncio import get_event_loop
from faulthandler import enable as faulthandler_enable
from logging import ERROR, INFO, StreamHandler, basicConfig, getLogger, handlers
import uvloop
import uvloop, uvicorn
from apscheduler.jobstores.mongodb import MongoDBJobStore
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from async_pymongo import AsyncClient
from pymongo import MongoClient
from pyrogram import Client
from web.webserver import api
from misskaty.vars import (
API_HASH,
@ -21,6 +22,7 @@ from misskaty.vars import (
BOT_TOKEN,
DATABASE_NAME,
DATABASE_URI,
PORT,
TZ,
USER_SESSION,
)
@ -83,6 +85,11 @@ jobstores = {
}
scheduler = AsyncIOScheduler(jobstores=jobstores, timezone=TZ)
async def run_wsgi():
config = uvicorn.Config(api, host="0.0.0.0", port=int(PORT))
server = uvicorn.Server(config)
await server.serve()
app.start()
BOT_ID = app.me.id
BOT_NAME = app.me.first_name

View file

@ -24,6 +24,7 @@ from misskaty import (
app,
get_event_loop,
scheduler,
run_wsgi
)
from misskaty.plugins import ALL_MODULES
from misskaty.plugins.web_scraper import web
@ -56,7 +57,6 @@ async def start_bot():
LOGGER.info(bot_modules)
LOGGER.info("+===============+===============+===============+===============+")
LOGGER.info("[INFO]: BOT STARTED AS @%s!", BOT_USERNAME)
try:
LOGGER.info("[INFO]: SENDING ONLINE STATUS")
for i in SUDO:
@ -73,6 +73,7 @@ async def start_bot():
except Exception as e:
LOGGER.error(str(e))
scheduler.start()
asyncio.create_task(run_wsgi())
if "web" not in await dbname.list_collection_names():
webdb = dbname["web"]
for key, value in web.items():

View file

@ -4,10 +4,12 @@ import html
import io
import json
import os
import hashlib
import pickle
import platform
import privatebinapi
import re
import secrets
import sys
import traceback
from datetime import datetime
@ -22,6 +24,7 @@ import cloudscraper
import requests
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from bs4 import BeautifulSoup
from urllib.parse import quote
from PIL import Image, ImageDraw, ImageFont
from psutil import Process, boot_time, cpu_count, cpu_percent
from psutil import disk_usage as disk_usage_percent
@ -44,6 +47,7 @@ from pyrogram.types import (
LabeledPrice,
Message,
PreCheckoutQuery,
WebAppInfo,
)
from database.gban_db import add_gban_user, is_gbanned_user, remove_gban_user
@ -55,7 +59,8 @@ from misskaty.helper.functions import extract_user, extract_user_and_reason
from misskaty.helper.http import fetch
from misskaty.helper.human_read import get_readable_file_size, get_readable_time
from misskaty.helper.localization import use_chat_lang
from misskaty.vars import AUTO_RESTART, COMMAND_HANDLER, LOG_CHANNEL, SUDO
from database.payment_db import autopay_update
from misskaty.vars import AUTO_RESTART, COMMAND_HANDLER, LOG_CHANNEL, SUDO, PAYDISINI_CHANNEL_ID, PAYDISINI_KEY
__MODULE__ = "DevCommand"
__HELP__ = """
@ -179,6 +184,45 @@ async def log_file(_, ctx: Message, strings):
else:
await msg.edit_msg("Unsupported parameter")
@app.on_message(filters.command(["payment"], COMMAND_HANDLER))
async def payment(client: Client, message: Message):
api_url = 'https://api.paydisini.co.id/v1/'
api_key = PAYDISINI_KEY
unique_id = f"VIP-{secrets.token_hex(5)}"
amount = "10000" if len(message.command) == 1 else str(message.command[1])
id_ = message.from_user.id if message.chat.id != message.from_user.id else message.chat.id
valid_time = str(5*60)
service_id = PAYDISINI_CHANNEL_ID
params = {
'key': api_key,
'request': 'new',
'unique_code': unique_id,
'service': service_id,
'amount': amount,
'note': f'MissKaty Support by YS Dev',
'valid_time': valid_time,
'type_fee': '1',
'payment_guide': True,
'signature': hashlib.md5((api_key + unique_id + service_id + amount + valid_time + 'NewTransaction').encode()).hexdigest(),
'return_url': f'https://t.me/{client.me.username}?start'
}
# if id_ in user_data and user_data[id_].get("is_auth"):
# return await message.reply("Already Authorized!")
rget = await fetch.post(api_url, data=params)
if rget.status_code != 200:
return await message.reply("ERROR: Maybe your IP is not whitelisted or have another error from api.")
res = rget.json()
if not res.get("success"):
return await message.reply(res["msg"])
qr_photo = f"https://api.qrserver.com/v1/create-qr-code/?size=300x300&data={quote(res['data']['qr_content'])}"
capt = f"𝗠𝗲𝗻𝘂𝗻𝗴𝗴𝘂 𝗽𝗲𝗺𝗯𝗮𝘆𝗮𝗿𝗮𝗻\nKode: {res['data']['unique_code']}\nNote: {res['data']['note']}\nHarga: {res['data']['amount']}\nFee: {res['data']['fee']}\nExpired: {res['data']['expired']}\n\n"
payment_guide = f"<b>{res['payment_guide'][0]['title']}:</b>\n" + "\n".join(f"{i+1}. {step}" for i, step in enumerate(res["payment_guide"][0]['content']))
if message.chat.type.value != "private":
msg = await message.reply_photo(qr_photo, caption=capt+payment_guide, reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(text="Payment Web", url=res["data"]["checkout_url_v2"])]]), quote=True)
else:
msg = await message.reply_photo(qr_photo, caption=capt+payment_guide, reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(text="Payment Web", web_app=WebAppInfo(url=res["data"]["checkout_url_v2"]))]]), quote=True)
await autopay_update(msg.id, res["data"]["note"], id_, res['data']['amount'], res['data']['status'], res['data']['unique_code'], res['data']['created_at'])
@app.on_message(filters.command(["donate"], COMMAND_HANDLER))
async def donate(self: Client, ctx: Message):

View file

@ -50,6 +50,7 @@ LOG_GROUP_ID = environ.get("LOG_GROUP_ID")
USER_SESSION = environ.get("USER_SESSION")
DATABASE_NAME = environ.get("DATABASE_NAME", "MissKatyDB")
TZ = environ.get("TZ", "Asia/Jakarta")
PORT = environ.get("PORT", 80)
COMMAND_HANDLER = environ.get("COMMAND_HANDLER", "! /").split()
SUDO = list(
{
@ -64,6 +65,8 @@ SUPPORT_CHAT = environ.get("SUPPORT_CHAT", "YasirPediaChannel")
AUTO_RESTART = environ.get("AUTO_RESTART", False)
OPENAI_KEY = environ.get("OPENAI_KEY")
GOOGLEAI_KEY = environ.get("GOOGLEAI_KEY")
PAYDISINI_KEY = environ.get("PAYDISINI_KEY")
PAYDISINI_CHANNEL_ID = environ.get("PAYDISINI_CHANNEL_ID", "17")
## Config For AUtoForwarder
# Forward From Chat ID

View file

@ -34,3 +34,6 @@ GitPython
aiofiles
uvloop==0.19.0
lxml_html_clean
fastapi
uvicorn
python-multipart

98
web/webserver.py Normal file
View file

@ -0,0 +1,98 @@
from logging import INFO, StreamHandler, basicConfig, getLogger, ERROR, handlers
from os import path
from time import time
from datetime import datetime, timedelta
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse, JSONResponse
from starlette.exceptions import HTTPException
from psutil import boot_time, disk_usage, net_io_counters
from contextlib import suppress
from asyncio import to_thread, subprocess, create_subprocess_shell
from apscheduler.triggers.date import DateTrigger
import hashlib
api = FastAPI()
basicConfig(
level=INFO,
format="[%(levelname)s] - [%(asctime)s - %(name)s - %(message)s] -> [%(module)s:%(lineno)d]",
datefmt="%d-%b-%y %H:%M:%S",
handlers=[
handlers.RotatingFileHandler(
"MissKatyLogs.txt", mode="w+", maxBytes=5242880, backupCount=1
),
StreamHandler(),
],
)
botStartTime = time()
LOGGER = getLogger(__name__)
getLogger("fastapi").setLevel(ERROR)
@api.post("/callback")
async def autopay(request: Request):
from misskaty import app
from database.payment_db import delete_autopay, get_autopay
from misskaty.vars import PAYDISINI_KEY, OWNER_ID
data = await request.form()
client_ip = request.client.host
if PAYDISINI_KEY != data["key"] and client_ip != "84.247.150.90":
raise HTTPException(status_code=403, detail="Access forbidden")
signature_data = f"{PAYDISINI_KEY}{data['unique_code']}CallbackStatus"
gen_signature = hashlib.md5(signature_data.encode()).hexdigest()
if gen_signature != data["signature"]:
raise HTTPException(status_code=403, detail="Invalid Signature")
unique_code = data['unique_code']
status = data['status']
exp_date = (datetime.now(jkt) + timedelta(days=30)).strftime("%Y-%m-%d %H:%M:%S")
r = await get_autopay(unique_code)
msg = f"╭────〔 <b>TRANSAKSI SUKSES🎉</b> 〕──\n│・ <b>Transaksi ID :</b> {unique_code}\n│・ <b>Product :</b> MissKaty Support by YS Dev\n│・ <b>Durasi :</b> 30 hari\n│・ <b>Total Dibayar :</b> {r.get('amount')}\n│・ Langganan Berakhir: {exp_date}\n╰─────────"
if not r:
return JSONResponse({"status": false, "data": "Data not found on DB"}, 404)
if status == "Success":
with suppress(Exception):
await bot.send_message(r.get("user_id"), f"{msg}\n\nJika ada pertanyaan silahkan hubungi pemilik bot ini.")
await bot.delete_messages(r.get("user_id"), r.get("msg_id"))
await bot.send_message(OWNER_ID, msg)
await delete_autopay(unique_code)
return JSONResponse({"status": status, "msg": "Pesanan berhasil dibayar oleh customer."}, 200)
else:
with suppress(Exception):
await bot.send_message(r.get("user_id"), "QRIS Telah Expired, Silahkan Buat Transaksi Baru.")
await bot.delete_messages(r.get("user_id"), r.get("msg_id"))
await delete_autopay(unique_code)
return JSONResponse({"status": status, "msg": "Pesanan telah dibatalkan/gagal dibayar."}, 403)
@api.get("/status")
async def status():
from misskaty.helper.human_read import get_readable_file_size, get_readable_time
bot_uptime = get_readable_time(time() - botStartTime)
uptime = get_readable_time(time() - boot_time())
sent = get_readable_file_size(net_io_counters().bytes_sent)
recv = get_readable_file_size(net_io_counters().bytes_recv)
if path.exists(".git"):
commit_date = (await (await create_subprocess_shell("git log -1 --date=format:'%y/%m/%d %H:%M' --pretty=format:'%cd'", stdout=subprocess.PIPE, stderr=subprocess.STDOUT)).communicate())[0].decode()
else:
commit_date = "No UPSTREAM_REPO"
return {
"commit_date": commit_date,
"uptime": uptime,
"on_time": bot_uptime,
"free_disk": get_readable_file_size(disk_usage(".").free),
"total_disk": get_readable_file_size(disk_usage(".").total),
"network": {
"sent": sent,
"recv": recv,
},
}
@api.api_route("/")
async def homepage():
return "Hello World"
@api.exception_handler(HTTPException)
async def page_not_found(request: Request, exc: HTTPException):
return HTMLResponse(content=f"<h1>Error: {exc}</h1>", status_code=exc.status_code)