aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore108
-rw-r--r--LICENSE21
-rw-r--r--SmallYTChannelBotSubmissions.py315
-rw-r--r--archive_posts.py25
-rw-r--r--database.py95
-rw-r--r--onceaday.py9
-rw-r--r--runprog.py23
-rw-r--r--test_ytapi.py69
-rw-r--r--ytapi.py90
9 files changed, 755 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..8b220d0
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,108 @@
+login.py
+graph.png
+
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.vs/
+.Python
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+
+# PyInstaller
+# Usually these files are written by a python script from a template
+# before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+.hypothesis/
+.pytest_cache/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+db.sqlite3
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# pyenv
+.python-version
+
+# celery beat schedule file
+celerybeat-schedule
+
+# SageMath parsed files
+*.sage.py
+
+# Environments
+.env
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..5e307b0
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2018 jwansek
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/SmallYTChannelBotSubmissions.py b/SmallYTChannelBotSubmissions.py
new file mode 100644
index 0000000..110baa5
--- /dev/null
+++ b/SmallYTChannelBotSubmissions.py
@@ -0,0 +1,315 @@
+from mpl_toolkits.axes_grid1 import host_subplot
+import mpl_toolkits.axisartist as AA
+from imgurpython import ImgurClient
+import matplotlib.pyplot as plt
+from operator import itemgetter
+from database import Database
+import matplotlib
+import datetime
+import ytapi
+import login
+import time
+import praw
+import re
+import os
+
+reddit = login.REDDIT
+
+subreddit = reddit.subreddit("SmallYTChannel")
+#subreddit = reddit.subreddit("jwnskanzkwktest")
+
+db = Database()
+
+def get_time():
+ #this is not the correct way to do this but I don't care
+ return str(datetime.datetime.now().time())[:8]
+
+def get_lambda_from_flair(s):
+ result = re.search("\[(.*)\]", s)
+ if result is not None and "λ" in result.group(1):
+ return result.group(1)
+ else:
+ return ""
+
+def update_users_flair(comment):
+ username = str(comment.author)
+ flairscore = get_lambda_from_flair(str(comment.author_flair_text))
+ flairtext = comment.author_flair_text
+ if flairtext is None:
+ flairtext = ""
+ else:
+ flairtext = str(flairtext.replace("[%s] " % flairscore, ""))
+ if username in [str(i) for i in subreddit.moderator()] + ["AutoModerator"]:
+ newflair = "[∞λ] %s" % (flairtext)
+ else:
+ actualscore = db.get_lambda(username)[0]
+ newflair = "[%iλ] %s" % (actualscore, flairtext)
+ subreddit.flair.set(redditor = username, text = newflair)
+
+def get_mods():
+ return [str(i) for i in subreddit.moderator()] + ["AutoModerator"]
+
+def _make_graph(data):
+ fig = plt.figure()
+
+ lambdaCount = [i[1] for i in data]
+ helpGiven = [i[2] for i in data]
+ uniqueUsers = [i[3] for i in data]
+ date = [datetime.datetime.strptime(i[4], "%Y-%m-%d") for i in data]
+
+ fig, ax1 = plt.subplots()
+ ax1.plot(date, lambdaCount, label = "Total λ given", color = "r")
+ ax1.set_ylabel("Total λ / help given")
+
+ ax1.plot(date, helpGiven, label = "Times help given", color = "g")
+
+ ax2 = ax1.twinx()
+ ax2.plot(date, uniqueUsers, label = "Unique users")
+ ax2.set_ylabel("No. Unique Users")
+
+ ax1.legend()
+ ax2.legend(loc = 4)
+ fig.autofmt_xdate()
+
+ filepath = "graph.png"
+ fig.savefig(filepath)
+ return filepath
+
+def _update_tables(scores, data):
+ content = ""
+ date = str(datetime.date.today())
+ mods = get_mods()
+ imagepath = _make_graph(data)
+ imageurl = _upload_image(imagepath, date)
+ bylambda = [i for i in sorted(scores, key = itemgetter(1), reverse = True) if i[0] not in mods][:10]
+ byhelps = sorted(scores, key = itemgetter(2), reverse = True)[:10]
+
+ subreddit.stylesheet.upload("wikigraph", imagepath)
+
+ content += "\n\n##/r/SmallYTChannel lambda tables: %s" % date
+
+ content += "\n\n###By lambda:"
+ content += "\n\nUsername|Lambda|Help given\n:--|:--|:--"
+ for line in bylambda:
+ content += "\n/u/%s|%i|%i" % (line[0], line[1], line[2])
+
+ content += "\n\n###By Help given:"
+ content += "\n\nUsername|Lambda|Help given\n:--|:--|:--"
+ for line in byhelps:
+ λ = str(line[1])
+ if line[0] in mods:
+ λ = "∞"
+ content += "\n/u/%s|%s|%i" % (line[0], λ, line[2])
+
+ content += "\n\n##Statistics from %s:\n\n![](%%%%wikigraph%%%%)\n\nTotal λ given|Useful advice given|Unique users\n:--|:--|:--\n%i|%i|%i" % (date, data[-1][1], data[-1][2], data[-1][3])
+
+ reddit.subreddit("u_SmallYTChannelBot").submit("/r/SmallYTChannel Statistics: %s" % date, url = imageurl).reply(content).mod.distinguish(sticky = True)
+
+ subreddit.wiki["lambdatables"].edit(content, reason = "Update: %s" % date)
+ subreddit.wiki[date].edit(content, reason = "Update: %s" % date)
+
+ currentdata = subreddit.wiki["index"].content_md
+ currentdata += "\n\n* [%s](/r/SmallYTChannel/wiki/%s)" % (date, date)
+
+ subreddit.wiki["index"].edit(currentdata, reason = "Update: %s" % date)
+
+def _upload_image(path, date):
+ client = login.IMGUR
+
+ config = {
+ 'album': None,
+ 'name': 'SmallYTChannelBot Statistics graph: %s' % date,
+ 'title': 'SmallYTChannelBot Statistics graph: %s' % date,
+ 'description': 'SmallYTChannelBot Statistics graph: %s' % date
+ }
+
+ image = client.upload_from_path(path, config = config)
+
+ return "https://i.imgur.com/%s.png" % image["id"]
+
+def every_day():
+ db.update_stats()
+ _update_tables(db.get_scores(), db.get_stats())
+
+def main():
+ tail = "\n\n\n ^/u/SmallYTChannelBot ^*made* ^*by* ^/u/jwnskanzkwk. ^*PM* ^*for* ^*bug* ^*reports.* ^*For* ^*more* ^*information,* ^*read* ^*the* ^[FAQ.](https://www.reddit.com/user/SmallYTChannelBot/comments/a4u7qj/smallytchannelbot_faq/)"
+
+ comment_stream = subreddit.stream.comments(pause_after=-1)
+ submission_stream = subreddit.stream.submissions(pause_after=-1)
+ while True:
+ try:
+ for comment in comment_stream:
+ if comment is None:
+ break
+ if not db.id_in_blacklist(comment.id):
+ db.add_to_blacklist(comment.id)
+
+ if "!mylambda" in comment.body.lower() and str(comment.author) != "SmallYTChannelBot":
+ author = str(comment.author)
+ λ, links = db.get_lambda(author)
+ if author in get_mods():
+ text = "/u/%s is a moderator, and therefore has ∞λ." % author
+ else:
+ if λ == 0:
+ text = "/u/%s has 0λ." % author
+ else:
+ text = "/u/%s has %iλ, from helping the following posts:" % (author, λ)
+ count = 0
+ for link in links:
+ if "www.reddit.com" not in link:
+ link = "https://www.reddit.com" + link
+
+ #set a max limit on the number of times this will iterate to stop it
+ #breaking because of Reddit's character limit.
+ count += 1
+ text += "\n\n- [%s](%s)" % (reddit.submission(url = link).title, link)
+ if count > 20: #experminent with this number
+ text += "\n\n[%i more...]" % len(links) - count
+ break
+
+ reply = comment.reply(text + tail)
+ reply.mod.distinguish(sticky = False)
+ update_users_flair(comment)
+
+
+ if "!givelambda" in comment.body.lower() and str(comment.author) != "SmallYTChannelBot":
+ submission = comment.submission
+ parentauthour = str(comment.parent().author)
+ op = str(comment.author)
+ if op == parentauthour:
+ text = "You cannot give yourself λ."
+ elif parentauthour == "SmallYTChannelBot":
+ text = "Please only give lambda to humans."
+ elif str(comment.author) in get_mods():
+ text = "The moderator /u/%s has given /u/%s 1λ. /u/%s now has %iλ." % (str(comment.author), parentauthour, parentauthour, db.get_lambda(parentauthour)[0] + 1)
+ db.give_lambda(parentauthour, submission.permalink)
+ elif op != str(submission.author):
+ text = "Only the OP can give λ."
+ elif db.user_given_lambda(parentauthour, str(submission.permalink)):
+ text = "You have already given /u/%s λ for this submission. Why not give λ to another user instead?" % parentauthour
+ else:
+ print("[%s] '/u/%s' has given '/u/%s' lambda!" % (get_time(), op, parentauthour))
+ text = "You have given /u/%s 1λ. /u/%s now has %iλ" % (parentauthour, parentauthour, db.get_lambda(parentauthour)[0] + 1)
+
+ if not db.link_in_db(submission.permalink) or not db.link_in_db(submission.permalink.replace("https://www.reddit.com", "")):
+ db.give_lambda(parentauthour, submission.permalink, op)
+ print("The OP has received lambda too!")
+ else:
+ db.give_lambda(parentauthour, submission.permalink)
+
+ update_users_flair(comment)
+ update_users_flair(comment.parent())
+ reply = comment.reply(text + tail)
+ reply.mod.distinguish()
+
+ if comment.body[:11] == "!takelambda" and str(comment.author) in get_mods():
+ try:
+ splitted = comment.body.split()
+ user = splitted[1].replace("/u/", "")
+ toremove = int(splitted[2])
+ reason = " ".join(splitted[3:])
+
+ text = "/u/%s has had %iλ taken away from them for the reason '%s'. /u/%s now has %iλ" % (user, toremove, reason, user, db.get_lambda(user)[0] - toremove)
+ db.change_lambda(user, -toremove)
+ except Exception as e:
+ print("[ERROR while removing λ] %s" % e)
+ text = r"An error was encountered. Please use the syntax `!takelambda [user] [how much to remove {integer}] [reason]`"
+ reply = comment.reply(text + tail)
+ reply.mod.distinguish()
+ continue
+
+ update_users_flair(comment.parent())
+ reply = comment.reply(text + tail)
+ reply.mod.distinguish()
+
+
+ for submission in submission_stream:
+ if submission is None:
+ break
+ if not db.id_in_blacklist(submission.id):
+ db.add_to_blacklist(submission.id)
+ print("[%s] There has been a new submission: '%s', with flair '%s'" % (get_time(), submission.title, submission.link_flair_text))
+
+ if str(submission.author) not in get_mods():
+ score = db.get_lambda(str(submission.author))[0]
+ if submission.link_flair_text in ["Discussion", "Meta", "Collab"]:
+ if "youtube.com" in str(submission.url) or "youtu.be" in str(submission.url):
+ text = "Your post has been removed because it has the wrong flair. [Discussion], [Meta] and [Collab] flairs are only for text submissions."
+ submission.mod.remove()
+ else:
+ text = "Your post is a discussion, meta or collab post so it costs 0λ."
+ else:
+ if score < 3:
+ text = """Thank you for submitting to /r/SmallYTChannel. Unfortunally, you submission has been removed since you do not have enough λ. You need
+ 3λ to post. You currently have %iλ. For more information, read the [FAQ](https://www.reddit.com/user/SmallYTChannelBot/comments/a4u7qj/smallytchannelbot_faq/)""" % score
+ submission.mod.remove()
+ else:
+ text = """Thank you for submitting to /r/SmallYTChannel. You have spent 3λ to submit here, making your current balance %iλ.
+ /u/%s, please comment `!givelambda` to the most helpful advice you are given. You
+ will be rewarded 1λ if you do so. For more information, read the [FAQ](https://www.reddit.com/user/SmallYTChannelBot/comments/a4u7qj/smallytchannelbot_faq/)""" % (score - 3, str(submission.author))
+ db.change_lambda(str(submission.author), -3)
+
+ ytid = ytapi.get_videoId_from_url(submission.url)
+ if "/" not in ytid:
+ ytdata = ytapi.get_video_data(ytid)
+
+ text += """
+\n\n\n##Video data:
+
+Field|Data
+:-|:-
+Title|%s
+Thumbnail|[Link](%s)
+Views|%s
+Length|%s
+Likes/Dislikes|%s/%s
+Comments|%s
+Description|%s
+
+##Channel Data:
+
+Field|Data
+:-|:-
+Name|%s
+Thumbnail|[Link](%s)
+Subscribers|%s
+Videos|%s
+Views|%s
+ """ % (
+ ytdata["title"],
+ ytdata["thumbnail"],
+ ytdata["views"],
+ ytdata["length"],
+ ytdata["likes"],
+ ytdata["dislikes"],
+ ytdata["comments"],
+ ytdata["description"],
+ ytdata["channel"],
+ ytdata["channelThumb"],
+ ytdata["subscribers"],
+ ytdata["videos"],
+ ytdata["channelViews"]
+ )
+
+ curflair = submission.link_flair_text
+ if str(curflair) != "None":
+ submission.mod.flair(" %s | %s | :youtube: %s" % (curflair, ytdata["length"], ytdata["channel"]))
+ else:
+ submission.mod.flair("%s | :youtube: %s" % (ytdata["length"], ytdata["channel"]))
+
+ update_users_flair(submission)
+ reply = submission.reply(text + tail)
+ reply.mod.distinguish(sticky = True)
+
+ except Exception as e:
+ print("[ERROR]\t%s" % e)
+ continue
+
+if __name__ == "__main__":
+ #file = open("pid.txt", "w")
+ #file.write(str(os.getpid()))
+ #file.close()
+
+ print("\n####################\n[%s] RESTARTED\n####################\n" % get_time())
+ main()
+
diff --git a/archive_posts.py b/archive_posts.py
new file mode 100644
index 0000000..a68feaf
--- /dev/null
+++ b/archive_posts.py
@@ -0,0 +1,25 @@
+import praw
+import database
+import login
+
+reddit = login.REDDIT
+
+subreddit = reddit.subreddit("jwnskanzkwktest")
+db = database.Database()
+
+comment_stream = subreddit.stream.comments(pause_after=-1)
+submission_stream = subreddit.stream.submissions(pause_after=-1)
+while True:
+ for comment in comment_stream:
+ if comment is None:
+ break
+ if not db.id_in_blacklist(comment.id):
+ print("archived: ", comment.id)
+ db.add_to_blacklist(comment.id)
+
+ for submission in submission_stream:
+ if submission is None:
+ break
+ if not db.id_in_blacklist(submission.id):
+ print("archived: ", submission.id)
+ db.add_to_blacklist(submission.id) \ No newline at end of file
diff --git a/database.py b/database.py
new file mode 100644
index 0000000..26b8e43
--- /dev/null
+++ b/database.py
@@ -0,0 +1,95 @@
+import sqlite3
+
+class Database:
+ def __init__(self):
+ self.connection = sqlite3.connect("SmallYTChannelDatabase.db")
+ self.cursor = self.connection.cursor()
+
+ def change_lambda(self, user, changeby):
+ #this will make it go negative. You must check this operation is allowed.
+ self.cursor.execute("UPDATE users SET lambda = ((SELECT lambda FROM users WHERE user_name = ?) + ?) WHERE user_name = ?;", (user, changeby, user))
+ self.connection.commit()
+
+ def give_lambda(self, user, link, op = None):
+ def give(user, link = None):
+ #check if the user has an entry in the database
+ self.cursor.execute("SELECT userID FROM users WHERE user_name = ?;", (user, ))
+ try:
+ id_ = self.cursor.fetchone()[0]
+ except TypeError:
+ #the user isn't in the database
+ self.cursor.execute("INSERT INTO users (user_name, lambda) VALUES (?, 1);", (user, ))
+ self.connection.commit()
+ if link is not None:
+ self.cursor.execute("INSERT INTO lambdas (userID, permalink) VALUES ((SELECT userID FROM users WHERE user_name = ?), ?);", (user, link))
+ else:
+ #update their lambda and add to lambdas
+ self.change_lambda(user, 1)
+ if link is not None:
+ self.cursor.execute("INSERT INTO lambdas (userID, permalink) VALUES (?, ?);", (id_, link))
+
+ self.connection.commit()
+
+ #give one lambda to both the user and the OP
+ give(user, link)
+ if op is not None:
+ give(op)
+
+ def get_lambda(self, user):
+ self.cursor.execute("SELECT lambda FROM users WHERE user_name = ?", (user, ))
+ try:
+ lambda_ = self.cursor.fetchone()[0]
+ except TypeError:
+ #the user isn't in the database, and therefore has no lambda
+ return 0, []
+ else:
+ self.cursor.execute("SELECT permalink FROM lambdas WHERE userID = (SELECT userID FROM users WHERE user_name = ?);", (user, ))
+ links = [i[0] for i in self.cursor.fetchall()]
+
+ return lambda_, links
+
+ def link_in_db(self, link):
+ self.cursor.execute("SELECT permalink FROM lambdas;")
+ try:
+ links = [i[0] for i in self.cursor.fetchall()]
+ except TypeError:
+ links = []
+
+ return link in links
+
+ def add_to_blacklist(self, id):
+ self.cursor.execute("INSERT INTO blacklist (prawID) VALUES (?);", (id, ))
+ self.connection.commit()
+
+ def id_in_blacklist(self, id):
+ self.cursor.execute("SELECT prawID FROM blacklist;")
+ try:
+ ids = [i[0] for i in self.cursor.fetchall()]
+ except TypeError:
+ ids = []
+
+ return id in ids
+
+ def get_scores(self):
+ self.cursor.execute("SELECT users.user_name, users.lambda, COUNT(users.user_name) FROM lambdas INNER JOIN users ON users.userID = lambdas.userID GROUP BY users.user_name;")
+ return self.cursor.fetchall()
+
+ def update_stats(self):
+ query = """INSERT INTO stats (lambdaCount, helpGiven, uniqueUsers, date) VALUES (
+ (SELECT SUM(lambda) FROM users),
+ (SELECT COUNT(lambdaID) FROM lambdas),
+ (SELECT COUNT(user_name) FROM users),
+ (SELECT strftime('%Y-%m-%d')));"""
+
+ self.cursor.execute(query)
+ self.connection.commit()
+
+ def get_stats(self):
+ self.cursor.execute("SELECT * FROM stats;")
+ return self.cursor.fetchall()
+
+ def user_given_lambda(self, user, permalink):
+ links = self.get_lambda(user)[1]
+ return permalink in links or permalink.replace("https://www.reddit.com", "") in links
+
+
diff --git a/onceaday.py b/onceaday.py
new file mode 100644
index 0000000..a84b0d9
--- /dev/null
+++ b/onceaday.py
@@ -0,0 +1,9 @@
+import SmallYTChannelBotSubmissions
+from time import sleep
+
+SECONDS_IN_DAY = 25 * 60 * 60
+
+while True:
+ SmallYTChannelBotSubmissions.every_day()
+ print("Called @ %s" % SmallYTChannelBotSubmissions.get_time)
+ sleep(SECONDS_IN_DAY)
diff --git a/runprog.py b/runprog.py
new file mode 100644
index 0000000..a564678
--- /dev/null
+++ b/runprog.py
@@ -0,0 +1,23 @@
+from time import sleep
+import subprocess
+import multiprocessing
+
+def thread_():
+ subprocess.run(["python3", "SmallYTChannelBotSubmissions.py"])
+
+while True:
+ thread = multiprocessing.Process(target = thread_, args = ())
+ thread.start()
+
+ sleep(60 * 60 * 2)
+
+ #print("closing...")
+ #file = open("pid.txt", "r")
+ #pid = file.readlines()[0]
+ #file.close()
+
+ #subprocess.run(["kill", pid])
+ thread.terminate()
+
+ #print("killed ", pid)
+
diff --git a/test_ytapi.py b/test_ytapi.py
new file mode 100644
index 0000000..44f439f
--- /dev/null
+++ b/test_ytapi.py
@@ -0,0 +1,69 @@
+import praw
+import database
+import login
+import ytapi
+
+reddit = login.REDDIT
+
+subreddit = reddit.subreddit("jwnskanzkwktest")
+
+tail = "\n\n\n ^/u/SmallYTChannelBot ^*made* ^*by* ^/u/jwnskanzkwk. ^*PM* ^*for* ^*bug* ^*reports.* ^*For* ^*more* ^*information,* ^*read* ^*the* ^[FAQ.](https://www.reddit.com/user/SmallYTChannelBot/comments/a4u7qj/smallytchannelbot_faq/)"
+
+submission_stream = subreddit.stream.submissions(pause_after=-1)
+while True:
+
+ for submission in submission_stream:
+ if submission is not None:
+
+ text = "Thank you for submitting..."
+ ytid = ytapi.get_videoId_from_url(submission.url)
+ if "/" not in ytid:
+ ytdata = ytapi.get_video_data(ytid)
+
+ text += """
+\n\n\n##Video data:
+
+Field|Data
+:-|:-
+Title|%s
+Thumbnail|[Link](%s)
+Views|%s
+Length|%s
+Likes/Dislikes|%s/%s
+Comments|%s
+Description|%s
+
+##Channel Data:
+
+Field|Data
+:-|:-
+Name|%s
+Thumbnail|[Link](%s)
+Subscribers|%s
+Videos|%s
+Views|%s
+
+ """ % (
+ ytdata["title"],
+ ytdata["thumbnail"],
+ ytdata["views"],
+ ytdata["length"],
+ ytdata["likes"],
+ ytdata["dislikes"],
+ ytdata["comments"],
+ ytdata["description"],
+ ytdata["channel"],
+ ytdata["channelThumb"],
+ ytdata["subscribers"],
+ ytdata["videos"],
+ ytdata["channelViews"]
+ )
+
+ curflair = submission.link_flair_text
+ if str(curflair) != "None":
+ submission.mod.flair(" %s | %s | :youtube: %s" % (curflair, ytdata["length"], ytdata["channel"]))
+ else:
+ submission.mod.flair("%s | :youtube: %s" % (ytdata["length"], ytdata["channel"]))
+
+ reply = submission.reply(text + tail)
+ reply.mod.distinguish(sticky = True)
diff --git a/ytapi.py b/ytapi.py
new file mode 100644
index 0000000..b472b7e
--- /dev/null
+++ b/ytapi.py
@@ -0,0 +1,90 @@
+from googleapiclient.discovery import build
+from googleapiclient.errors import HttpError
+import js2py
+
+ERROR_DICT = {
+ "title": "ERROR Video deleted?",
+ "description": "ERROR Video deleted?",
+ "channel": "ERROR Video deleted?",
+ "subscribers": "ERROR Video deleted?",
+ "videos": "ERROR Video deleted?",
+ "channelViews": "ERROR Video deleted?",
+ "channelThumb": "ERROR Video deleted?",
+ "thumbnail": "ERROR Video deleted?",
+ "length": "ERROR Video deleted?",
+ "views": "ERROR Video deleted?",
+ "likes": "ERROR Video deleted?",
+ "dislikes": "ERROR Video deleted?",
+ "comments": "ERROR Video deleted?"
+ }
+
+# Set DEVELOPER_KEY to the API key value from the APIs & auth > Registered apps
+# tab of
+# https://cloud.google.com/console
+# Please ensure that you have enabled the YouTube Data API for your project.
+DEVELOPER_KEY = 'AIzaSyBQsuU5GgCTZdFi7cBmPQHWZwIa545zLUE'
+YOUTUBE_API_SERVICE_NAME = 'youtube'
+YOUTUBE_API_VERSION = 'v3'
+
+#run JavaScript because I don't understand regular expressions so we can copy this bad boy from Stack Overflow
+get_videoId_from_url = js2py.eval_js(r"""function $(url){
+ var re = /https?:\/\/(?:[0-9A-Z-]+\.)?(?:youtu\.be\/|youtube(?:-nocookie)?\.com\S*?[^\w\s-])([\w-]{11})(?=[^\w-]|$)(?![?=&+%\w.-]*(?:['"][^<>]*>|<\/a>))[?=&+%\w.-]*/ig;
+ return url.replace(re, '$1');
+ }""")
+
+def _yt_time_to_norm(time):
+ if time == "ERROR Video deleted?":
+ return time
+
+ time = time.replace("M", ":")[2:].replace("S", "")
+
+ s = time.split(":")
+ if len(s) > 1:
+ if len(s[1]) < 2:
+ time = s[0] + ":" + s[1] + "0"
+
+ return time
+
+#this would be better as a class but I can't be bothered so dictionary it is
+def get_video_data(videoId):
+ youtube = build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION, developerKey=DEVELOPER_KEY)
+
+
+ #youTubeData = youtube.videos().list(part = "snippet", id = videoId).execute()["items"][0]["snippet"]
+
+ #return {"title": youTubeData["title"], "description": youTubeData["description"], "tags": youTubeData["tags"]}
+
+ try:
+ youTubeData = youtube.videos().list(part = "snippet,contentDetails,statistics", id = videoId).execute()["items"][0]
+ except IndexError:
+ return ERROR_DICT
+
+ snippet = youTubeData["snippet"]
+ length = youTubeData["contentDetails"]["duration"]
+ stats = youTubeData["statistics"]
+ channelId = snippet["channelId"]
+
+ channelData = youtube.channels().list(part = 'snippet,statistics', id = channelId).execute()["items"][0]
+
+ return {
+ "title": snippet["title"],
+ "description": snippet["description"].replace("\n", "⤶"),
+ "channel": channelData["snippet"]["title"],
+ "subscribers": channelData["statistics"]["subscriberCount"],
+ "videos": channelData["statistics"]["videoCount"],
+ "channelViews": channelData["statistics"]["viewCount"],
+ "channelThumb": channelData["snippet"]["thumbnails"]["high"]["url"],
+ "thumbnail": snippet["thumbnails"]["high"]["url"],
+ "length": _yt_time_to_norm(length),
+ "views": stats["viewCount"],
+ "likes": stats["likeCount"],
+ "dislikes": stats["dislikeCount"],
+ "comments": stats["commentCount"]
+ }
+
+
+if __name__ == '__main__':
+ try:
+ print(get_channel_data("https://www.youtube.com/watch?v=XPpAkggrdaU&feature=youtu.be"))
+ except HttpError as e:
+ print('An HTTP error %d occurred:\n%s' % (e.resp.status, e.content)) \ No newline at end of file