Guest User

op-helper.py v0.2 by C-Anon

a guest
Sep 28th, 2022
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.46 KB | None | 0 0
  1. #!/usr/bin/env python3
  2. # op-helper.py for making threads on /vt/
  3. # Released under MIT License, software is provided as-is and all that crap.
  4. # v0.2 by C-Anon
  5.  
  6. import re, json, urllib.request
  7. import datetime, time
  8.  
  9.  
  10. ##########################
  11. #   CONFIGURATION
  12.  
  13. # Ignore streams if they're set this amount of days from now (or more)
  14. ignore_days = 10
  15.  
  16. # Sort streams by starting timestamp
  17. sort_streams = False
  18.  
  19. # Show stream titles
  20. show_live_titles = False
  21. show_upcoming_titles = False
  22.  
  23. # Show timezones
  24. show_timezones = False
  25.  
  26. # If true, data is output to a file instead of the terminal
  27. output_to_file = True
  28. outfname = 'op-helper.txt'
  29.  
  30. # Channel data
  31. #   The format is channel ID followed by a space, then followed
  32. #   by the name of the channel. Empty lines are ignored
  33. channel_data = """
  34. UC8P3OkWBUsrk93f1pV0b5bQ Ageha Himeragi
  35. UCEnhASxlFG-ZPCpYDTYIQZA Charo Nemurime
  36. UCAx0YWXJgyvXx5oDvrDaN_A Himari Inumaki
  37. UCvm34tgJ0ZaKzTinWVyXpcA Himea D'Almaria
  38. UC6tSB9TnO0f01OBeo9UEJZA Hina Misora
  39. UCVtuciDzkjxCP_O7r-0QhXQ Ito Shinonome
  40. UCJePO0Zl-zZTqjpHO82RNNA Lia Mitsurugi
  41. UCN3mosAMYBdogyQovOhPrxA Luna Rurine
  42. UClXfBZMVxt-JgNMaHGr5NMQ Mahiru Kumaboshi
  43. UCUUjykb68Lf85CbWX6gAmog Mireille Kuuma
  44. UCM6iy_rSgSMbFjx10Z6VVGA Miu Hizuki
  45. UCIm8pnnTNhCgGAtNxrQQv-g Yue Saohime
  46. """
  47.  
  48. # Timezone data
  49. #   You can specify timezones to display along with the other information.
  50. #   The format is the name of the timezone followed by a space, then followed
  51. #   by the number of hours from UTC (e.g. Mexico City timezone is GMT-5 in summer)
  52. #
  53. #   This might need to be adjusted as countries adopt and abandon daylight savings time
  54. #   throughout the year.
  55. timezone_data = """
  56. MEX -5
  57. ARG -3
  58. ESP 2
  59. JAP 9
  60. """
  61.  
  62. #   END OF CONFIGURATION
  63. ##########################
  64.  
  65. now = time.time
  66.  
  67. def getStreams(channel_id, channel_owner):
  68.     url = 'https://www.youtube.com/channel/%s/' % (channel_id)
  69.     headers = {
  70.         'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:104.0) Gecko/20100101 Firefox/104.0',
  71.         'Accept-Language': 'en-US,en;q=0.5'
  72.     }
  73.  
  74.     try:
  75.         req = urllib.request.Request(url, headers=headers)
  76.         conn = urllib.request.urlopen(req)
  77.     except (urllib.error.URLError, ValueError) as e:
  78.         print("Error! Couldn't retrieve URL. ", str(e).capitalize())
  79.         return
  80.     response = conn.read().decode('utf-8')
  81.     temp = re.findall('<script nonce="[^"]+">var ytInitialData = (.*?);</script>', response)
  82.     if not temp:
  83.         return
  84.  
  85.     streams = {}
  86.     json_obj = json.loads(temp[0])
  87.     first_tab = json_obj['contents']['twoColumnBrowseResultsRenderer']['tabs'][0]
  88.     for section in first_tab['tabRenderer']['content']['sectionListRenderer']['contents']:
  89.         if 'shelfRenderer' not in section['itemSectionRenderer']['contents'][0]:
  90.             continue
  91.         shelf_type = section['itemSectionRenderer']['contents'][0]['shelfRenderer']['title']['runs'][0]['text']
  92.         if  shelf_type not in ['Live now', 'Upcoming live streams']:
  93.             continue
  94.  
  95.         if 'expandedShelfContentsRenderer' not in section['itemSectionRenderer']['contents'][0]['shelfRenderer']['content']:
  96.             row = section['itemSectionRenderer']['contents'][0]['shelfRenderer']['content']['horizontalListRenderer']['items']
  97.             vrname = 'gridVideoRenderer'
  98.         else:
  99.             row = section['itemSectionRenderer']['contents'][0]['shelfRenderer']['content']['expandedShelfContentsRenderer']['items']
  100.             vrname = 'videoRenderer'
  101.         for elem in row:
  102.             new_stream = {'videoId': '', 'type'   : '', 'start'  : '', 'title'  : '', 'owner':''}
  103.             if shelf_type == "Live now":
  104.                 new_stream['videoId'] = elem[vrname]['videoId']
  105.                 new_stream['type']    = "live"
  106.                 new_stream['start']   = ""
  107.                 new_stream['owner']   = channel_owner
  108.                 new_stream['title']   = elem[vrname]['title']['simpleText']
  109.                 if 'live' not in streams:
  110.                     streams['live'] = [new_stream]
  111.                 else:
  112.                     streams['live'].append(new_stream)
  113.             elif shelf_type == "Upcoming live streams":
  114.                 if 'upcomingEventData' not in elem[vrname]:
  115.                     continue
  116.                 new_stream['videoId'] = elem[vrname]['videoId']
  117.                 new_stream['type']    = "upcoming"
  118.                 new_stream['start']   = elem[vrname]['upcomingEventData']['startTime']
  119.                 new_stream['owner']   = channel_owner
  120.                 new_stream['title']   = elem[vrname]['title']['simpleText']
  121.                 if 'upcoming' not in streams:
  122.                     streams['upcoming'] = [new_stream]
  123.                 else:
  124.                     streams['upcoming'].append(new_stream)
  125.     return streams
  126.  
  127. def getTimeString(ts):
  128.     ret = ""
  129.     last_date = ""
  130.     for tz in timezones:
  131.         dts = ts + (tz['delta'] * 3600)
  132.         dts = datetime.datetime.utcfromtimestamp(dts)
  133.         date = datetime.datetime.strftime(dts, '%Y-%m-%d')
  134.         if last_date != date:
  135.             ret += date + " "
  136.         ret += datetime.datetime.strftime(dts, '%H:%M') + " " + tz['name'] + " "
  137.         last_date = date
  138.     return ret
  139.  
  140. def log(txt):
  141.     if output_to_file and fp:
  142.         fp.write(txt + "\n")
  143.     else:
  144.         print(txt)
  145.  
  146. channels = []
  147. for line in channel_data.splitlines():
  148.     if not line or line == "":
  149.         continue
  150.     tmp = line.split(' ')
  151.     channels.append({'channelId': tmp[0], 'channelOwner': " ".join(tmp[1:])})
  152.  
  153. timezones = []
  154. for line in timezone_data.splitlines():
  155.     if not line or line == "":
  156.         continue
  157.     tmp = line.split(' ')
  158.     timezones.append({'name': tmp[0], 'delta': float(tmp[1])})
  159.  
  160. # Sort timezones
  161. timezones = sorted(timezones, key=lambda kv: kv['delta'])
  162.  
  163. live_streams = []
  164. upcoming_streams = []
  165. # Retrieve information from channels
  166. for chan in channels:
  167.     print("Retrieving %s channel (%s)" % (chan['channelOwner'], chan['channelId']))
  168.     streams = getStreams(chan['channelId'], chan['channelOwner'])
  169.     if not streams:
  170.         continue
  171.     if 'live' in streams:
  172.         live_streams += streams['live']
  173.     if 'upcoming' in streams:
  174.         upcoming_streams += streams['upcoming']
  175.  
  176. if output_to_file:
  177.     fp = open(outfname, 'w', encoding='utf-8')
  178.  
  179. live_streams = sorted(live_streams, key=lambda kv: kv['owner'])
  180. if live_streams:
  181.     log('LIVE STREAMS:')
  182.     last_owner = ""
  183.     for stream in live_streams:
  184.         if stream['owner'] != last_owner:
  185.             log("\n" + stream['owner'])
  186.         if show_live_titles:
  187.             log(stream['title'])
  188.         log("https://youtu.be/%s" % stream['videoId'])
  189.         last_owner = stream['owner']
  190. log("")
  191. if sort_streams:
  192.     upcoming_streams = sorted(upcoming_streams, key=lambda kv: kv['start'])
  193. if upcoming_streams:
  194.     log('UPCOMING STREAMS:')
  195.     last_owner = ''
  196.     for stream in upcoming_streams:
  197.         # If upcoming stream is more than 'ignore_days' days away, ignore it
  198.         if now() + (60 * 60 * 24 * ignore_days) < int(stream['start']):
  199.             continue
  200.  
  201.         timestr = getTimeString(int(stream['start']))
  202.         if stream['owner'] != last_owner:
  203.             log("\n" + stream['owner'])
  204.         if show_upcoming_titles:
  205.             log(stream['title'])
  206.         log("https://youtu.be/%s" % (stream['videoId']))
  207.         if show_timezones:
  208.             log(timestr)
  209.         last_owner = stream['owner']
  210. if output_to_file:
  211.     print("Output to file %s" % outfname)
  212.  
Advertisement
Add Comment
Please, Sign In to add comment