Skip to content

Commit

Permalink
manyvids support, proxy support, requirements update, nodriver improv…
Browse files Browse the repository at this point in the history
…emens, docker improvements
  • Loading branch information
Bombg committed Oct 22, 2024
1 parent 51cb9b4 commit 7140d0d
Show file tree
Hide file tree
Showing 20 changed files with 210 additions and 33 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ KickScreenshot.jpg
ofScreenshot.jpg
NoDriverTest.py
AppConstants.py
tests
tests
.dockerignore
53 changes: 45 additions & 8 deletions DefaultConstants.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,28 @@ class Constants:
BC_NOTIFICATION_CHANNEL_ID = 1137599805787480214
SC_NOTIFICATION_CHANNEL_ID = 1137599805787480214
EP_NOTIFICATION_CHANNEL_ID = 1137599805787480214
MV_NOTIFICATION_CHANNEL_ID = 1137599805787480214
CONFESSTION_CHANNEL_ID = 1137599805787480214

CONFESSION_COMMAND_ID = 1159423004346957835
CONFESS_REVIEW_COMMAND_ID = 1159423004346957834

KICK_PROXY = ""
FANS_PROXY = "127.0.0.1:8888"
OF_PROXY = ""

# Leave an empty string if you don't wish to use a proxy for a checker.
# Kick/OF/Fansly use nodriver, which doesn't support authenticated proxies
# All the other platforms assumes you're using a socks5 proxy, so you can leave out the socks5:// part
# Commented out platforms don't support proxies
KICK_PROXY = "" # Chrome/Chromium doesn't support authenticated proxies
FANS_PROXY = "127.0.0.1:8888" # Chrome/Chromium doesn't support authenticated proxies
OF_PROXY = "" # Chrome/Chromium doesn't support authenticated proxies
#CB_PROXY = "" # Everything below assumed is a socks5 proxy.
MV_PROXY = ""
BC_PROXY = ""
SC_PROXY = ""
EP_PROXY = ""
CAM4_PROXY = ""
MFC_PROXY = ""
#YT_PROXY = ""
#TWITCH_PROXY = ""
else:
GUILD_ID =1058859922219081778 #Guild ID of the discord server
whiteListedRoleIDs = [1062179283705020486,145802742647095296,1100148453792813086,245364417783398400] # IDs of Roles you wish to be white listed for some commands. You can also add user IDs if you want to add an individual without a role
Expand All @@ -41,14 +55,28 @@ class Constants:
BC_NOTIFICATION_CHANNEL_ID = 1268796965743886448
SC_NOTIFICATION_CHANNEL_ID = 1268796965743886448
EP_NOTIFICATION_CHANNEL_ID = 1268796965743886448
MV_NOTIFICATION_CHANNEL_ID = 1268796965743886448
CONFESSTION_CHANNEL_ID = 1158240422997528637

CONFESSION_COMMAND_ID = 1159321755270250571
CONFESS_REVIEW_COMMAND_ID = 1159321755270250570

KICK_PROXY = ""
FANS_PROXY = "127.0.0.1:8888"
OF_PROXY = ""

# Leave an empty string if you don't wish to use a proxy for a checker.
# Kick/OF/Fansly use nodriver, which doesn't support authenticated proxies
# All the other platforms assumes you're using a socks5 proxy, so you can leave out the socks5:// part
# Commented out platforms don't support proxies
KICK_PROXY = "" # Chrome/Chromium doesn't support authenticated proxies
FANS_PROXY = "127.0.0.1:8888" # Chrome/Chromium doesn't support authenticated proxies
OF_PROXY = ""# Chrome/Chromium doesn't support authenticated proxies
#CB_PROXY = "" # Everything below assumed is a socks5 proxy.
MV_PROXY = ""
BC_PROXY = ""
SC_PROXY = ""
EP_PROXY = ""
CAM4_PROXY = ""
MFC_PROXY = ""
#YT_PROXY = ""
#TWITCH_PROXY = ""

WAIT_BETWEEN_MESSAGES = 1800 # minimum amount of time in seconds the stream has to be offline before new notification messages.
MIN_TIME_BEFORE_AVATAR_CHANGE = 48 # Minimum time before avatar changes -- in hours
Expand All @@ -74,6 +102,7 @@ class Constants:
BC_CHECK_TIMER = 180
SC_CHECK_TIMER = 180
EP_CHECK_TIMER = 180
MV_CHECK_TIMER = 180

AVATAR_CHECK_TIMER = 130 # Timer for checking last online time before changing between happy/angry avatars
STATUS_CHECK_TIMER = 125 # Timer for checking online status and changing the bot status. Also used for record keeping
Expand Down Expand Up @@ -107,6 +136,7 @@ class Constants:
BC_ROLES_TO_PING = "@everyone "
SC_ROLES_TO_PING = "@everyone "
EP_ROLES_TO_PING = "@everyone "
MV_ROLES_TO_PING = "@everyone "

# For rerun announcements/pings to work you will first need to turn them on via the /announce-rerun-toggle True/False command AND the /ping-toggle True/False command.
# if you don't want a specific platform to get a rerun ping, just leave an empty string (It will still get announced if turned on)
Expand All @@ -125,6 +155,7 @@ class Constants:
BC_RERUN_ROLES_TO_PING = ""
SC_RERUN_ROLES_TO_PING = ""
EP_RERUN_ROLES_TO_PING = ""
MV_RERUN_ROLES_TO_PING = ""

#Generic name of the streamer that will be used for all notifications
streamerName = "LitneySpears"
Expand All @@ -142,6 +173,7 @@ class Constants:
bcUserName = []
scUserName = []
epUserName = []
mvUserName = [] #case sensitive if you want the the avatar to be pulled

twitchUrl = f"https://www.twitch.tv/litneyspears_" #Add a valid twitch URL here even if you streamer doesn't have twitch or else the presence won't update properly

Expand All @@ -163,6 +195,7 @@ class Constants:
bcEmbedColor = "#97323a"
scEmbedColor = "#a02831"
epEmbedColor = "#f03d4c"
mvEmbedColor = "#722a9e"

# Mainly Used in stream-status command
linkTreeUrl = "https://allmylinks.com/litneyspears"
Expand All @@ -178,6 +211,7 @@ class Constants:
bcDefaultTitle = "BongaCams Fun Time."
scDefaultTitle = "StripChat Fun Time."
epDefaultTitle = "ePlay Fun Time."
mvDefaultTitle = "Manyvids Fun Time Starts Now!"

# This is the text that will appear above the embed. Role mentions will be added before this text, and a link to the stream will be added after
# i.e. @everyone <AboveEmbedTextGoesHere> https://kick.com/StreamerName
Expand All @@ -192,6 +226,7 @@ class Constants:
bcAboveEmbedText = f"{streamerName} is live on BongaCams!"
scAboveEmbedText = f"{streamerName} is live on StripChat!"
epAboveEmbedText = f"{streamerName} is live on ePlay!"
mvAboveEmbedText = f"{streamerName} is live on ManyVids!"

# This is small text that will appear below the title, and above the main image inside the embed.
kickBelowTitleText = f"{streamerName} is now live on Kick!"
Expand All @@ -205,6 +240,7 @@ class Constants:
bcBelowTitleText = f"{streamerName} is now live on BongaCams!"
scBelowTitleText = f"{streamerName} is now live on StripChat!"
epBelowTitleText = f"{streamerName} is now live on ePlay!"
mvBelowTitleText = f"{streamerName} is now live on ManyVids!"

# Leave empty strings if you want to use default thumbnail behavior; which is: (1)pull thumbnail from platform, (2)if it doesn't exist use image from image list, (3)if list empty use defaultThumbnail
# Add your own image path/url if you want to exclusively use the same image over and over for a specific platform's thumbnail
Expand All @@ -220,6 +256,7 @@ class Constants:
bcThumbnail = ""
scThumbnail = ""
epThumbnail = ""
mvThumbnail = ""

# Icon in this case is the small image that shows in the top left of the imbed before the streamer's name for that platform
# This is used if an avatar/icon can't be found on a platform, otherwise the platform's version will be used
Expand Down
28 changes: 20 additions & 8 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,19 +1,31 @@
# syntax=docker/dockerfile:1
FROM python:3.11.3-slim
# Build Stage
FROM python:3.11.3-slim AS build

ENV DEBIAN_FRONTEND=noninteractive

# Install dependencies
RUN apt update -y
RUN apt install -y chromium xvfb git
RUN apt update -y && apt install -y git

WORKDIR /opt/SassBot
COPY . .
RUN python3 -m venv /venv
ENV PATH=/venv/bin:$PATH

# Clone repo and install requirements
COPY requirements.txt .
RUN pip install -r requirements.txt && \
pip install uvloop

# Buidling final image, moving over venv
FROM python:3.11.3-slim

ENV DEBIAN_FRONTEND=noninteractive

WORKDIR /opt/SassBot

RUN apt update -y && apt install -y --no-install-recommends chromium xvfb

COPY --from=build /venv /venv
ENV PATH=/venv/bin:$PATH

COPY . .

RUN chmod +x docker-entrypoint.sh

ENTRYPOINT ["/bin/sh", "-c", "./docker-entrypoint.sh"]
3 changes: 2 additions & 1 deletion GenerateDatabase.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@
("mfc",0,0,0),
("bongacams",0,0,0),
("stripchat",0,0,0),
("eplay",0,0,0)
("eplay",0,0,0),
("manyvids",0,0,0)
]
subathon_values =[
(0,0,0,0,None)
Expand Down
8 changes: 8 additions & 0 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
- BongaCams
- StripChat
- ePlay
- ManyVids
### Features
- Get notifications when your streamer is online sent to a discord channel
- Rerun detection/support. If stream titles contains a variation of rerun/rr/not live then it will be detected as a rerun.
Expand Down Expand Up @@ -97,6 +98,13 @@
4. If the requesting ip is in a state that requires age verification, some of these checkers wont work.

### Update History
- 10/22/2024
- Added ManyVids Support
- Because of this many things have changed in Default/App Constants so they will need to be updated with new vars
- Added proxy support for most of the checkers. Anything that doesn't use nodriver will use socks5
- Changed requirements update them with 'pip install -U -r requirements.txt'
- Change nodriver temp file behavior. Uses default behavior in windows
- Changed Dockerfile to improve size and fixed docker image to work with windows
- 10/19/2024
- Improvements on Twitch checker to hopefully work more quickly
- Improvements with nodriver temp folders (was previously taking up too much disk space)
Expand Down
6 changes: 5 additions & 1 deletion checkers/Bongacams.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from utils.NoDriverBrowserCreator import getUserAgent
import logging
from utils.StaticMethods import GetThumbnail
from utils.StaticMethods import GetProxies

logger = logging.getLogger(__name__)
logger.setLevel(Constants.SASSBOT_LOG_LEVEL)
Expand All @@ -21,7 +22,10 @@ def isModelOnline(bcUserName):
agent = getUserAgent()
headers = {"User-Agent": agent}
try:
page = requests.get(f'https://bongacams.com/{bcUserName}',headers=headers)
if Constants.BC_PROXY:
page = requests.get(f'https://bongacams.com/{bcUserName}',headers=headers, proxies=GetProxies(Constants.BC_PROXY))
else:
page = requests.get(f'https://bongacams.com/{bcUserName}',headers=headers)
time.sleep(1)
if page.status_code == 200:
soup = BeautifulSoup(page.content, "html.parser")
Expand Down
6 changes: 5 additions & 1 deletion checkers/Cam4.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from utils.NoDriverBrowserCreator import getUserAgent
import logging
from utils.StaticMethods import GetThumbnail
from utils.StaticMethods import GetProxies

logger = logging.getLogger(__name__)
logger.setLevel(Constants.SASSBOT_LOG_LEVEL)
Expand All @@ -21,7 +22,10 @@ def isModelOnline(cam4UserName):
agent = getUserAgent()
try:
headers = {"User-Agent": agent}
results = requests.get(f"https://www.cam4.com/rest/v1.0/search/performer/{cam4UserName}", headers=headers)
if Constants.CAM4_PROXY:
results = requests.get(f"https://www.cam4.com/rest/v1.0/search/performer/{cam4UserName}", headers=headers, proxies=GetProxies(Constants.CAM4_PROXY))
else:
results = requests.get(f"https://www.cam4.com/rest/v1.0/search/performer/{cam4UserName}", headers=headers)
time.sleep(1)
try:
cam4Json = results.json()
Expand Down
9 changes: 8 additions & 1 deletion checkers/Eplay.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import json
import logging
from utils.StaticMethods import GetThumbnail
from utils.StaticMethods import GetProxies

logger = logging.getLogger(__name__)
logger.setLevel(Constants.SASSBOT_LOG_LEVEL)
Expand All @@ -18,13 +19,19 @@ def isModelOnline(epUserName):
tempThumbUrl = ""
icon = Constants.defaultIcon
try:
request = requests.get(f"https://eplay.com/{epUserName}")
if Constants.EP_PROXY:
request = requests.get(f"https://eplay.com/{epUserName}", proxies=GetProxies(Constants.EP_PROXY))
else:
request = requests.get(f"https://eplay.com/{epUserName}")
time.sleep(1)
soup = BeautifulSoup(request.content, "html.parser")
profileJson = soup.find_all("script", type="application/json")
profileJson = json.loads(profileJson[0].text)
isOnline = profileJson["props"]["pageProps"]["dehydratedState"]["queries"][0]["state"]["data"]["live"]
title = profileJson["props"]["pageProps"]["dehydratedState"]["queries"][0]["state"]["data"]["title"]
title = title.replace('\u200b', '')
title = title.replace('\r', '')
title = title.replace('\n', '')
tempThumbUrl = profileJson["props"]["pageProps"]["dehydratedState"]["queries"][0]["state"]["data"]["ss"] + "?" + str(int(time.time()))
icon = profileJson["props"]["pageProps"]["dehydratedState"]["queries"][0]["state"]["data"]["avatar"]
except requests.exceptions.ConnectTimeout:
Expand Down
43 changes: 43 additions & 0 deletions checkers/Manyvids.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import requests
from bs4 import BeautifulSoup
try:
from AppConstants import Constants as Constants
except ImportError:
from DefaultConstants import Constants as Constants
from utils.StaticMethods import GetThumbnail
from utils.StaticMethods import GetProxies
import logging
import re

logger = logging.getLogger(__name__)
logger.setLevel(Constants.SASSBOT_LOG_LEVEL)

def isModelOnline(mvUserName):
title = Constants.mvDefaultTitle
tempThumbUrl = ''
isOnline = False
icon = Constants.defaultIcon
pageUrl = f"https://www.manyvids.com/live/cam/{mvUserName.lower()}"
if Constants.MV_PROXY:
page = requests.get(pageUrl, proxies=GetProxies(Constants.MV_PROXY))
else:
page = requests.get(pageUrl)
soup = BeautifulSoup(page.content, "html.parser")
onlineStatus = soup.find("div", {"class":"status_box__v1drl"})
if onlineStatus:
logger.debug(onlineStatus.text)
else:
logger.debug("no online status")
if onlineStatus and (onlineStatus.text == "LIVE" or onlineStatus.text == "IN PRIVATE"):
isOnline = True
icon = GetIcon(soup, mvUserName)
thumbUrl = GetThumbnail(tempThumbUrl, Constants.mvThumbnail)
return isOnline, title, thumbUrl, icon

def GetIcon(soup:BeautifulSoup, mvUserName):
icon = Constants.defaultIcon
reString = r"https:\/\/cdn5\.manyvids\.com\/php_uploads\/profile\/" + mvUserName + r"\/image\/cropped-image_\d+.jpeg"
icon = re.search(reString, soup.prettify())
if icon:
icon = icon.group()
return icon
6 changes: 5 additions & 1 deletion checkers/Myfreecams.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from bs4 import BeautifulSoup
import logging
from utils.StaticMethods import GetThumbnail
from utils.StaticMethods import GetProxies

logger = logging.getLogger(__name__)
logger.setLevel(Constants.SASSBOT_LOG_LEVEL)
Expand All @@ -17,7 +18,10 @@ def isModelOnline(mfcUserName):
tempThumbUrl = ""
icon = Constants.defaultIcon
try:
request = requests.get(f"https://share.myfreecams.com/{mfcUserName}")
if Constants.MFC_PROXY:
request = requests.get(f"https://share.myfreecams.com/{mfcUserName}", proxies=GetProxies(Constants.MFC_PROXY))
else:
request = requests.get(f"https://share.myfreecams.com/{mfcUserName}")
time.sleep(1)
soup = BeautifulSoup(request.content, "html.parser")
vidPreview = soup.find(class_='campreview d-none')
Expand Down
6 changes: 5 additions & 1 deletion checkers/Stripchat.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from utils.NoDriverBrowserCreator import getUserAgent
import logging
from utils.StaticMethods import GetThumbnail
from utils.StaticMethods import GetProxies

logger = logging.getLogger(__name__)
logger.setLevel(Constants.SASSBOT_LOG_LEVEL)
Expand All @@ -20,7 +21,10 @@ def isModelOnline(scUserName):
agent = getUserAgent()
headers = {"User-Agent": agent}
try:
page = requests.get(f'https://stripchat.com/api/vr/v2/models/username/{scUserName}', headers=headers)
if Constants.SC_PROXY:
page = requests.get(f'https://stripchat.com/api/vr/v2/models/username/{scUserName}', headers=headers, proxies=GetProxies(Constants.SC_PROXY))
else:
page = requests.get(f'https://stripchat.com/api/vr/v2/models/username/{scUserName}', headers=headers)
time.sleep(1)
if page.status_code == 200:
try:
Expand Down
11 changes: 8 additions & 3 deletions checkers/Twitch.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ def isModelOnline(twitchChannelName: str):
isOnline = False
icon = Constants.defaultIcon
try:
tempThumbUrl = f'https://static-cdn.jtvnw.net/previews-ttv/live_user_{twitchChannelName}-640x360.jpg'
thumbUrlReq = requests.get(tempThumbUrl,allow_redirects=True)
isOnline = IsOnline(twitchChannelName)
time.sleep(1)
if tempThumbUrl == thumbUrlReq.url:
if isOnline:
isOnline = True
page = requests.get(f'https://www.twitch.tv/{twitchChannelName}')
tempThumbUrl = f'https://static-cdn.jtvnw.net/previews-ttv/live_user_{twitchChannelName}-640x360.jpg'
time.sleep(1)
soup = BeautifulSoup(page.content, "html.parser")
title = getTitle(soup)
Expand Down Expand Up @@ -54,3 +54,8 @@ def getTitle(soup):
except IndexError:
pass
return title

def IsOnline(channelName):
url = "https://gql.twitch.tv/gql"
query = "query {\n user(login: \""+ channelName +"\") {\n stream {\n id\n }\n }\n}"
return True if requests.request("POST", url, json={"query": query, "variables": {}}, headers={"client-id": "kimne78kx3ncx6brgo4mv6wki5h1ko"}).json()["data"]["user"]["stream"] else False
Loading

0 comments on commit 7140d0d

Please sign in to comment.