mirror of
https://github.com/yasirarism/MissKatyPyro.git
synced 2025-12-29 09:44:50 +00:00
Added Paydisini Integration (#309)
This commit is contained in:
parent
638cde6dd7
commit
3f6cd58db2
8 changed files with 176 additions and 4 deletions
|
|
@ -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
16
database/payment_db.py
Normal 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)
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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():
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -34,3 +34,6 @@ GitPython
|
|||
aiofiles
|
||||
uvloop==0.19.0
|
||||
lxml_html_clean
|
||||
fastapi
|
||||
uvicorn
|
||||
python-multipart
|
||||
|
|
|
|||
98
web/webserver.py
Normal file
98
web/webserver.py
Normal 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)
|
||||
Loading…
Reference in a new issue