Added rating and views to video information.

This commit is contained in:
Tiberiu Chibici 2018-10-22 01:02:51 +03:00
parent 6fd1c0a963
commit ab47484f54
13 changed files with 413 additions and 287 deletions

View File

@ -2,9 +2,19 @@
<project version="4"> <project version="4">
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="245751b6-c863-4572-8723-8499964fe105" name="Default Changelist" comment=""> <list default="true" id="245751b6-c863-4572-8723-8499964fe105" name="Default Changelist" comment="">
<change beforePath="$PROJECT_DIR$/YtManagerApp/models.py" beforeDir="false" afterPath="$PROJECT_DIR$/YtManagerApp/models.py" afterDir="false" /> <change afterPath="$PROJECT_DIR$/YtManagerApp/templatetags/__init__.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/YtManagerApp/scheduler.py" beforeDir="false" afterPath="$PROJECT_DIR$/YtManagerApp/scheduler.py" afterDir="false" /> <change afterPath="$PROJECT_DIR$/YtManagerApp/templatetags/common.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/YtManagerApp/views/actions.py" beforeDir="false" afterPath="$PROJECT_DIR$/YtManagerApp/views/actions.py" afterDir="false" /> <change afterPath="$PROJECT_DIR$/YtManagerApp/templatetags/ratings.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/YtManager/settings.py" beforeDir="false" afterPath="$PROJECT_DIR$/YtManager/settings.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/YtManagerApp/management/jobs/synchronize.py" beforeDir="false" afterPath="$PROJECT_DIR$/YtManagerApp/management/jobs/synchronize.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/YtManagerApp/management/videos.py" beforeDir="false" afterPath="$PROJECT_DIR$/YtManagerApp/management/videos.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/YtManagerApp/static/YtManagerApp/css/style.css" beforeDir="false" afterPath="$PROJECT_DIR$/YtManagerApp/static/YtManagerApp/css/style.css" afterDir="false" />
<change beforePath="$PROJECT_DIR$/YtManagerApp/static/YtManagerApp/css/style.css.map" beforeDir="false" afterPath="$PROJECT_DIR$/YtManagerApp/static/YtManagerApp/css/style.css.map" afterDir="false" />
<change beforePath="$PROJECT_DIR$/YtManagerApp/static/YtManagerApp/css/style.scss" beforeDir="false" afterPath="$PROJECT_DIR$/YtManagerApp/static/YtManagerApp/css/style.scss" afterDir="false" />
<change beforePath="$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/index_videos.html" beforeDir="false" afterPath="$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/index_videos.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/YtManagerApp/utils/iterutils.py" beforeDir="false" afterPath="$PROJECT_DIR$/YtManagerApp/utils/iterutils.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/YtManagerApp/utils/youtube.py" beforeDir="false" afterPath="$PROJECT_DIR$/YtManagerApp/utils/youtube.py" afterDir="false" />
</list> </list>
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" /> <option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
<option name="SHOW_DIALOG" value="false" /> <option name="SHOW_DIALOG" value="false" />
@ -68,32 +78,32 @@
</usages-collector> </usages-collector>
<usages-collector id="statistics.file.extensions.edit"> <usages-collector id="statistics.file.extensions.edit">
<counts> <counts>
<entry key="Django Console" value="254" /> <entry key="Django Console" value="401" />
<entry key="cell" value="32" /> <entry key="cell" value="42" />
<entry key="css" value="40" /> <entry key="css" value="40" />
<entry key="default" value="206" /> <entry key="default" value="206" />
<entry key="dummy" value="60" /> <entry key="dummy" value="60" />
<entry key="html" value="7623" /> <entry key="html" value="8218" />
<entry key="ini" value="2545" /> <entry key="ini" value="2545" />
<entry key="js" value="10149" /> <entry key="js" value="10149" />
<entry key="less" value="38" /> <entry key="less" value="38" />
<entry key="py" value="53601" /> <entry key="py" value="56123" />
<entry key="py@youtube-channel-manager" value="265" /> <entry key="py@youtube-channel-manager" value="265" />
<entry key="scss" value="1535" /> <entry key="scss" value="1647" />
</counts> </counts>
</usages-collector> </usages-collector>
<usages-collector id="statistics.file.types.edit"> <usages-collector id="statistics.file.types.edit">
<counts> <counts>
<entry key="CSS" value="40" /> <entry key="CSS" value="40" />
<entry key="CommandLine" value="148" /> <entry key="CommandLine" value="148" />
<entry key="HTML" value="7623" /> <entry key="HTML" value="8218" />
<entry key="Ini" value="2545" /> <entry key="Ini" value="2545" />
<entry key="JavaScript" value="10149" /> <entry key="JavaScript" value="10149" />
<entry key="Less" value="38" /> <entry key="Less" value="38" />
<entry key="PLAIN_TEXT" value="383" /> <entry key="PLAIN_TEXT" value="383" />
<entry key="Python" value="53855" /> <entry key="Python" value="56524" />
<entry key="SCSS" value="1535" /> <entry key="SCSS" value="1647" />
<entry key="Scratch" value="32" /> <entry key="Scratch" value="42" />
</counts> </counts>
</usages-collector> </usages-collector>
<usages-collector id="statistics.file.extensions.open"> <usages-collector id="statistics.file.extensions.open">
@ -102,131 +112,75 @@
<entry key="css" value="4" /> <entry key="css" value="4" />
<entry key="default" value="2" /> <entry key="default" value="2" />
<entry key="gif" value="1" /> <entry key="gif" value="1" />
<entry key="html" value="102" /> <entry key="html" value="105" />
<entry key="ini" value="9" /> <entry key="ini" value="10" />
<entry key="js" value="28" /> <entry key="js" value="28" />
<entry key="less" value="1" /> <entry key="less" value="1" />
<entry key="py" value="298" /> <entry key="py" value="313" />
<entry key="rnc" value="1" /> <entry key="rnc" value="1" />
<entry key="scss" value="28" /> <entry key="scss" value="29" />
<entry key="ytmanagerapp_channel" value="3" /> <entry key="ytmanagerapp_channel" value="3" />
<entry key="ytmanagerapp_subscription" value="8" /> <entry key="ytmanagerapp_subscription" value="8" />
<entry key="ytmanagerapp_subscriptionfolder" value="4" /> <entry key="ytmanagerapp_subscriptionfolder" value="4" />
<entry key="ytmanagerapp_video" value="13" /> <entry key="ytmanagerapp_video" value="15" />
</counts> </counts>
</usages-collector> </usages-collector>
<usages-collector id="statistics.file.types.open"> <usages-collector id="statistics.file.types.open">
<counts> <counts>
<entry key="CSS" value="4" /> <entry key="CSS" value="4" />
<entry key="Database Element" value="34" /> <entry key="Database Element" value="36" />
<entry key="HTML" value="102" /> <entry key="HTML" value="105" />
<entry key="Image" value="1" /> <entry key="Image" value="1" />
<entry key="Ini" value="9" /> <entry key="Ini" value="10" />
<entry key="JavaScript" value="28" /> <entry key="JavaScript" value="28" />
<entry key="Less" value="1" /> <entry key="Less" value="1" />
<entry key="PLAIN_TEXT" value="2" /> <entry key="PLAIN_TEXT" value="2" />
<entry key="Python" value="298" /> <entry key="Python" value="313" />
<entry key="RNG Compact" value="1" /> <entry key="RNG Compact" value="1" />
<entry key="SCSS" value="28" /> <entry key="SCSS" value="29" />
</counts> </counts>
</usages-collector> </usages-collector>
</session> </session>
</component> </component>
<component name="FileEditorManager"> <component name="FileEditorManager">
<splitter split-orientation="horizontal" split-proportion="0.3768394"> <leaf>
<split-first> <file pinned="false" current-in-tab="false">
<leaf SIDE_TABS_SIZE_LIMIT_KEY="300"> <entry file="file://C:/Python36/Lib/site-packages/django/template/base.py">
<file pinned="false" current-in-tab="true"> <provider selected="true" editor-type-id="text-editor">
<entry file="file://$PROJECT_DIR$/YtManagerApp/views/actions.py"> <state relative-caret-position="279">
<provider selected="true" editor-type-id="text-editor"> <caret line="759" column="23" selection-start-line="759" selection-start-column="23" selection-end-line="759" selection-end-column="23" />
<state relative-caret-position="459"> </state>
<caret line="58" lean-forward="true" selection-start-line="58" selection-end-line="58" /> </provider>
<folding> </entry>
<element signature="e#0#73#0" expanded="true" /> </file>
<marker date="1540074642385" expanded="true" signature="714:719" ph="..." /> <file pinned="false" current-in-tab="false">
</folding> <entry file="file://$PROJECT_DIR$/YtManagerApp/static/YtManagerApp/css/style.scss">
</state> <provider selected="true" editor-type-id="text-editor">
</provider> <state relative-caret-position="527">
</entry> <caret line="145" column="1" lean-forward="true" selection-start-line="145" selection-start-column="1" selection-end-line="145" selection-end-column="1" />
</file> </state>
<file pinned="false" current-in-tab="false"> </provider>
<entry file="file://$PROJECT_DIR$/YtManagerApp/urls.py"> </entry>
<provider selected="true" editor-type-id="text-editor"> </file>
<state relative-caret-position="187"> <file pinned="false" current-in-tab="true">
<caret line="38" column="63" selection-start-line="38" selection-start-column="63" selection-end-line="38" selection-end-column="63" /> <entry file="file://$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/index_videos.html">
<folding> <provider selected="true" editor-type-id="text-editor">
<element signature="e#643#675#0" expanded="true" /> <state relative-caret-position="391">
</folding> <caret line="23" column="56" selection-start-line="23" selection-start-column="56" selection-end-line="23" selection-end-column="56" />
</state> </state>
</provider> </provider>
</entry> </entry>
</file> </file>
<file pinned="false" current-in-tab="false"> <file pinned="false" current-in-tab="false">
<entry file="das://2dac2136-d902-4d27-8789-9371934602fd/schema/main/table/ytmanagerapp_video"> <entry file="das://2dac2136-d902-4d27-8789-9371934602fd/schema/main/table/ytmanagerapp_video">
<provider selected="true" editor-type-id="com.intellij.database.editor.DatabaseTableFileEditorProvider"> <provider selected="true" editor-type-id="com.intellij.database.editor.DatabaseTableFileEditorProvider">
<state> <state>
<filtering enabled="true" /> <filtering enabled="true" />
</state> </state>
</provider> </provider>
</entry> </entry>
</file> </file>
</leaf> </leaf>
</split-first>
<split-second>
<leaf>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/YtManagerApp/management/jobs/delete_video.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="68">
<caret line="4" selection-start-line="4" selection-end-line="4" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/YtManagerApp/models.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="119">
<caret line="293" column="12" selection-start-line="293" selection-start-column="12" selection-end-line="293" selection-end-column="12" />
<folding>
<element signature="e#0#14#0" expanded="true" />
<marker date="1540074893218" expanded="true" signature="4003:4146" ph="..." />
<marker date="1540074893218" expanded="true" signature="6543:6986" ph="..." />
<marker date="1540074893218" expanded="true" signature="9532:9541" ph="..." />
<marker date="1540074893218" expanded="true" signature="9532:9860" ph="..." />
<marker date="1540074893218" expanded="true" signature="9910:10438" ph="..." />
<marker date="1540074893218" expanded="true" signature="10410:10438" ph="..." />
<marker date="1540074893218" expanded="true" signature="12057:13169" ph="..." />
<marker date="1540074893218" expanded="true" signature="12992:13169" ph="..." />
</folding>
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/YtManagerApp/appconfig.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="136">
<caret line="8" selection-start-line="8" selection-end-line="8" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/YtManagerApp/scheduler.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="102">
<caret line="6" lean-forward="true" selection-start-line="6" selection-end-line="6" />
<folding>
<element signature="e#0#14#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
</leaf>
</split-second>
</splitter>
</component> </component>
<component name="FileTemplateManagerImpl"> <component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES"> <option name="RECENT_TEMPLATES">
@ -293,16 +247,12 @@
<component name="IdeDocumentHistory"> <component name="IdeDocumentHistory">
<option name="CHANGED_PATHS"> <option name="CHANGED_PATHS">
<list> <list>
<option value="$PROJECT_DIR$/YtManagerApp/templates/registration/password_reset_confirm.html" />
<option value="$PROJECT_DIR$/YtManagerApp/templates/registration/password_reset_complete.html" />
<option value="$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/index_unauth.html" />
<option value="$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/index_unauthenticated.html" /> <option value="$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/index_unauthenticated.html" />
<option value="$PROJECT_DIR$/YtManagerApp/views/auth.py" /> <option value="$PROJECT_DIR$/YtManagerApp/views/auth.py" />
<option value="$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/controls/dialog.html" /> <option value="$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/controls/dialog.html" />
<option value="$PROJECT_DIR$/YtManagerApp/views/dialog.py" /> <option value="$PROJECT_DIR$/YtManagerApp/views/dialog.py" />
<option value="$PROJECT_DIR$/YtManagerApp/views/modal.py" /> <option value="$PROJECT_DIR$/YtManagerApp/views/modal.py" />
<option value="$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/controls/common.js" /> <option value="$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/controls/common.js" />
<option value="$PROJECT_DIR$/YtManagerApp/utils/iterutils.py" />
<option value="$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/controls/modal_form.html" /> <option value="$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/controls/modal_form.html" />
<option value="$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/controls/folder_create_dialog.html" /> <option value="$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/controls/folder_create_dialog.html" />
<option value="$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/controls/folder_edit_dialog.html" /> <option value="$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/controls/folder_edit_dialog.html" />
@ -316,13 +266,11 @@
<option value="$PROJECT_DIR$/YtManagerApp/model/user_settings.py" /> <option value="$PROJECT_DIR$/YtManagerApp/model/user_settings.py" />
<option value="$PROJECT_DIR$/YtManagerApp/model/__init__.py" /> <option value="$PROJECT_DIR$/YtManagerApp/model/__init__.py" />
<option value="$PROJECT_DIR$/YtManagerApp/model/channel.py" /> <option value="$PROJECT_DIR$/YtManagerApp/model/channel.py" />
<option value="$PROJECT_DIR$/YtManagerApp/management/videos.py" />
<option value="$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/controls/subscription_create_modal.html" /> <option value="$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/controls/subscription_create_modal.html" />
<option value="$PROJECT_DIR$/YtManagerApp/management/management.py" /> <option value="$PROJECT_DIR$/YtManagerApp/management/management.py" />
<option value="$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/controls/modal.html" /> <option value="$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/controls/modal.html" />
<option value="$PROJECT_DIR$/YtManagerApp/views/controls/modal.py" /> <option value="$PROJECT_DIR$/YtManagerApp/views/controls/modal.py" />
<option value="$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/controls/subscription_update_modal.html" /> <option value="$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/controls/subscription_update_modal.html" />
<option value="$PROJECT_DIR$/YtManagerApp/utils/youtube.py" />
<option value="$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/controls/subscription_delete_modal.html" /> <option value="$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/controls/subscription_delete_modal.html" />
<option value="$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/controls/folder_delete_modal.html" /> <option value="$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/controls/folder_delete_modal.html" />
<option value="$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/js/subscription_tree.js" /> <option value="$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/js/subscription_tree.js" />
@ -331,19 +279,25 @@
<option value="$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/master_default.html" /> <option value="$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/master_default.html" />
<option value="$PROJECT_DIR$/YtManagerApp/apps.py" /> <option value="$PROJECT_DIR$/YtManagerApp/apps.py" />
<option value="$PROJECT_DIR$/YtManagerApp/utils/customconfigparser.py" /> <option value="$PROJECT_DIR$/YtManagerApp/utils/customconfigparser.py" />
<option value="$PROJECT_DIR$/YtManagerApp/static/YtManagerApp/css/style.scss" />
<option value="$PROJECT_DIR$/YtManagerApp/views/index.py" /> <option value="$PROJECT_DIR$/YtManagerApp/views/index.py" />
<option value="$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/js/index.js" /> <option value="$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/js/index.js" />
<option value="$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/js/common.js" /> <option value="$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/js/common.js" />
<option value="$PROJECT_DIR$/YtManagerApp/management/jobs/download_video.py" /> <option value="$PROJECT_DIR$/YtManagerApp/management/jobs/download_video.py" />
<option value="$PROJECT_DIR$/YtManagerApp/urls.py" /> <option value="$PROJECT_DIR$/YtManagerApp/urls.py" />
<option value="$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/index_videos.html" />
<option value="$PROJECT_DIR$/YtManagerApp/management/downloader.py" /> <option value="$PROJECT_DIR$/YtManagerApp/management/downloader.py" />
<option value="$PROJECT_DIR$/YtManagerApp/management/jobs/delete_video.py" /> <option value="$PROJECT_DIR$/YtManagerApp/management/jobs/delete_video.py" />
<option value="$PROJECT_DIR$/YtManagerApp/management/jobs/synchronize.py" />
<option value="$PROJECT_DIR$/YtManagerApp/views/actions.py" /> <option value="$PROJECT_DIR$/YtManagerApp/views/actions.py" />
<option value="$PROJECT_DIR$/YtManagerApp/scheduler.py" /> <option value="$PROJECT_DIR$/YtManagerApp/scheduler.py" />
<option value="$PROJECT_DIR$/YtManagerApp/models.py" /> <option value="$PROJECT_DIR$/YtManagerApp/models.py" />
<option value="$PROJECT_DIR$/YtManagerApp/management/videos.py" />
<option value="$PROJECT_DIR$/YtManagerApp/management/jobs/synchronize.py" />
<option value="$PROJECT_DIR$/YtManagerApp/utils/iterutils.py" />
<option value="$PROJECT_DIR$/YtManagerApp/utils/youtube.py" />
<option value="$PROJECT_DIR$/YtManager/settings.py" />
<option value="$PROJECT_DIR$/YtManagerApp/templatetags/common.py" />
<option value="$PROJECT_DIR$/YtManagerApp/templatetags/ratings.py" />
<option value="$PROJECT_DIR$/YtManagerApp/static/YtManagerApp/css/style.scss" />
<option value="$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/index_videos.html" />
</list> </list>
</option> </option>
</component> </component>
@ -359,10 +313,10 @@
</packageJsonPaths> </packageJsonPaths>
</component> </component>
<component name="ProjectFrameBounds" extendedState="6"> <component name="ProjectFrameBounds" extendedState="6">
<option name="x" value="58" /> <option name="x" value="72" />
<option name="y" value="-27" /> <option name="y" value="-8" />
<option name="width" value="1930" /> <option name="width" value="1928" />
<option name="height" value="973" /> <option name="height" value="963" />
</component> </component>
<component name="ProjectInspectionProfilesVisibleTreeState"> <component name="ProjectInspectionProfilesVisibleTreeState">
<entry key="Project Default"> <entry key="Project Default">
@ -439,19 +393,6 @@
<item name="youtube-channel-manager" type="462c0819:PsiDirectoryNode" /> <item name="youtube-channel-manager" type="462c0819:PsiDirectoryNode" />
<item name="YtManagerApp" type="462c0819:PsiDirectoryNode" /> <item name="YtManagerApp" type="462c0819:PsiDirectoryNode" />
</path> </path>
<path>
<item name="youtube-channel-manager" type="b2602c69:ProjectViewProjectNode" />
<item name="youtube-channel-manager" type="462c0819:PsiDirectoryNode" />
<item name="YtManagerApp" type="462c0819:PsiDirectoryNode" />
<item name="management" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="youtube-channel-manager" type="b2602c69:ProjectViewProjectNode" />
<item name="youtube-channel-manager" type="462c0819:PsiDirectoryNode" />
<item name="YtManagerApp" type="462c0819:PsiDirectoryNode" />
<item name="management" type="462c0819:PsiDirectoryNode" />
<item name="jobs" type="462c0819:PsiDirectoryNode" />
</path>
<path> <path>
<item name="youtube-channel-manager" type="b2602c69:ProjectViewProjectNode" /> <item name="youtube-channel-manager" type="b2602c69:ProjectViewProjectNode" />
<item name="youtube-channel-manager" type="462c0819:PsiDirectoryNode" /> <item name="youtube-channel-manager" type="462c0819:PsiDirectoryNode" />
@ -477,26 +418,7 @@
<item name="youtube-channel-manager" type="b2602c69:ProjectViewProjectNode" /> <item name="youtube-channel-manager" type="b2602c69:ProjectViewProjectNode" />
<item name="youtube-channel-manager" type="462c0819:PsiDirectoryNode" /> <item name="youtube-channel-manager" type="462c0819:PsiDirectoryNode" />
<item name="YtManagerApp" type="462c0819:PsiDirectoryNode" /> <item name="YtManagerApp" type="462c0819:PsiDirectoryNode" />
<item name="templates" type="462c0819:PsiDirectoryNode" /> <item name="templatetags" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="youtube-channel-manager" type="b2602c69:ProjectViewProjectNode" />
<item name="youtube-channel-manager" type="462c0819:PsiDirectoryNode" />
<item name="YtManagerApp" type="462c0819:PsiDirectoryNode" />
<item name="templates" type="462c0819:PsiDirectoryNode" />
<item name="YtManagerApp" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="youtube-channel-manager" type="b2602c69:ProjectViewProjectNode" />
<item name="youtube-channel-manager" type="462c0819:PsiDirectoryNode" />
<item name="YtManagerApp" type="462c0819:PsiDirectoryNode" />
<item name="utils" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="youtube-channel-manager" type="b2602c69:ProjectViewProjectNode" />
<item name="youtube-channel-manager" type="462c0819:PsiDirectoryNode" />
<item name="YtManagerApp" type="462c0819:PsiDirectoryNode" />
<item name="views" type="462c0819:PsiDirectoryNode" />
</path> </path>
</expand> </expand>
<select /> <select />
@ -514,7 +436,7 @@
<property name="list.type.of.created.stylesheet" value="SCSS" /> <property name="list.type.of.created.stylesheet" value="SCSS" />
<property name="nodejs_interpreter_path.stuck_in_default_project" value="undefined stuck path" /> <property name="nodejs_interpreter_path.stuck_in_default_project" value="undefined stuck path" />
<property name="nodejs_npm_path_reset_for_default_project" value="true" /> <property name="nodejs_npm_path_reset_for_default_project" value="true" />
<property name="settings.editor.selected.configurable" value="preferences.sourceCode.SCSS" /> <property name="settings.editor.selected.configurable" value="preferences.keymap" />
</component> </component>
<component name="RecentsManager"> <component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS"> <key name="CopyFile.RECENT_KEYS">
@ -674,12 +596,12 @@
<frame x="-8" y="-8" width="1936" height="1056" extended-state="6" /> <frame x="-8" y="-8" width="1936" height="1056" extended-state="6" />
<editor active="true" /> <editor active="true" />
<layout> <layout>
<window_info content_ui="combo" id="Project" order="0" visible="true" weight="0.16684435" /> <window_info active="true" content_ui="combo" id="Project" order="0" visible="true" weight="0.20469083" />
<window_info id="Structure" order="1" side_tool="true" weight="0.25" /> <window_info id="Structure" order="1" side_tool="true" weight="0.25" />
<window_info id="Favorites" order="2" side_tool="true" /> <window_info id="Favorites" order="2" side_tool="true" />
<window_info anchor="bottom" id="Message" order="0" /> <window_info anchor="bottom" id="Message" order="0" />
<window_info anchor="bottom" id="Find" order="1" sideWeight="0.4978678" weight="0.329718" /> <window_info anchor="bottom" id="Find" order="1" sideWeight="0.4978678" weight="0.329718" />
<window_info active="true" anchor="bottom" id="Run" order="2" sideWeight="0.5299353" visible="true" weight="0.3394794" /> <window_info anchor="bottom" id="Run" order="2" sideWeight="0.5299353" visible="true" weight="0.3394794" />
<window_info anchor="bottom" id="Debug" order="3" sideWeight="0.49946696" weight="0.2494577" /> <window_info anchor="bottom" id="Debug" order="3" sideWeight="0.49946696" weight="0.2494577" />
<window_info anchor="bottom" id="Cvs" order="4" weight="0.25" /> <window_info anchor="bottom" id="Cvs" order="4" weight="0.25" />
<window_info anchor="bottom" id="Inspection" order="5" weight="0.4" /> <window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
@ -696,7 +618,7 @@
<window_info anchor="right" id="Ant Build" order="1" weight="0.25" /> <window_info anchor="right" id="Ant Build" order="1" weight="0.25" />
<window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" /> <window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" />
<window_info anchor="right" id="SciView" order="3" weight="0.32995737" /> <window_info anchor="right" id="SciView" order="3" weight="0.32995737" />
<window_info anchor="right" id="Database" order="4" weight="0.13006397" /> <window_info anchor="right" id="Database" order="4" visible="true" weight="0.13006397" />
</layout> </layout>
<layout-to-restore> <layout-to-restore>
<window_info active="true" content_ui="combo" id="Project" order="0" visible="true" weight="0.15138593" /> <window_info active="true" content_ui="combo" id="Project" order="0" visible="true" weight="0.15138593" />
@ -731,32 +653,6 @@
<option name="myLimit" value="2678400000" /> <option name="myLimit" value="2678400000" />
</component> </component>
<component name="editorHistoryManager"> <component name="editorHistoryManager">
<entry file="file://$PROJECT_DIR$/YtManagerApp/management/folders.py" />
<entry file="file://$PROJECT_DIR$/YtManagerApp/management/management.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="384">
<caret line="92" selection-start-line="92" selection-end-line="110" selection-end-column="45" />
<folding>
<element signature="e#0#65#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/controls/subscription_create_modal.html">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="204">
<caret line="12" lean-forward="true" selection-start-line="12" selection-end-line="12" />
</state>
</provider>
</entry>
<entry file="file://C:/Python36/Lib/site-packages/googleapiclient/errors.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-1659">
<caret line="28" column="6" selection-start-line="28" selection-start-column="6" selection-end-line="28" selection-end-column="6" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/controls/subscription_edit_dialog.html" />
<entry file="das://2dac2136-d902-4d27-8789-9371934602fd/schema/main/table/ytmanagerapp_subscription"> <entry file="das://2dac2136-d902-4d27-8789-9371934602fd/schema/main/table/ytmanagerapp_subscription">
<provider selected="true" editor-type-id="com.intellij.database.editor.DatabaseTableFileEditorProvider"> <provider selected="true" editor-type-id="com.intellij.database.editor.DatabaseTableFileEditorProvider">
<state> <state>
@ -792,17 +688,6 @@
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/YtManagerApp/utils/youtube.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="765">
<caret line="49" column="23" selection-start-line="49" selection-start-column="23" selection-end-line="49" selection-end-column="23" />
<folding>
<element signature="e#0#43#0" expanded="true" />
<marker date="1539811805520" expanded="true" signature="411:557" ph="..." />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/controls/modal.html"> <entry file="file://$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/controls/modal.html">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="323"> <state relative-caret-position="323">
@ -860,16 +745,6 @@
<entry file="file://C:/Python36/Lib/logging/__init__.py"> <entry file="file://C:/Python36/Lib/logging/__init__.py">
<provider selected="true" editor-type-id="text-editor" /> <provider selected="true" editor-type-id="text-editor" />
</entry> </entry>
<entry file="file://$PROJECT_DIR$/YtManagerApp/management/videos.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="500">
<caret line="55" column="37" selection-start-line="55" selection-start-column="37" selection-end-line="55" selection-end-column="37" />
<folding>
<element signature="e#0#71#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/YtManager/urls.py"> <entry file="file://$PROJECT_DIR$/YtManager/urls.py">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="391"> <state relative-caret-position="391">
@ -945,34 +820,6 @@
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/YtManagerApp/static/YtManagerApp/css/style.scss">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="137">
<caret line="111" column="29" selection-start-line="111" selection-start-column="29" selection-end-line="111" selection-end-column="29" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/YtManagerApp/views/index.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="528">
<caret line="346" lean-forward="true" selection-start-line="346" selection-end-line="346" />
<folding>
<element signature="e#0#42#0" expanded="true" />
<marker date="1540023237405" expanded="true" signature="3128:3307" ph="..." />
<marker date="1540023237405" expanded="true" signature="3339:3340" ph="..." />
<marker date="1540023237405" expanded="true" signature="3646:3647" ph="..." />
<marker date="1540023237405" expanded="true" signature="3646:4387" ph="..." />
<marker date="1540023237405" expanded="true" signature="3668:4279" ph="..." />
<marker date="1540023237405" expanded="true" signature="4432:4436" ph="..." />
<marker date="1540023237405" expanded="true" signature="5221:6592" ph="..." />
<marker date="1540023237405" expanded="true" signature="5465:5470" ph="..." />
<marker date="1540023237405" expanded="true" signature="5491:5566" ph="..." />
<marker date="1540023237405" expanded="true" signature="6640:6641" ph="..." />
<marker date="1540023237405" expanded="true" signature="7201:7204" ph="..." />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/YtManagerApp/views/old_views.py"> <entry file="file://$PROJECT_DIR$/YtManagerApp/views/old_views.py">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="205"> <state relative-caret-position="205">
@ -1025,13 +872,6 @@
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="das://2dac2136-d902-4d27-8789-9371934602fd/schema/main/table/ytmanagerapp_video">
<provider selected="true" editor-type-id="com.intellij.database.editor.DatabaseTableFileEditorProvider">
<state>
<filtering enabled="true" />
</state>
</provider>
</entry>
<entry file="file://C:/Python36/Lib/mimetypes.py"> <entry file="file://C:/Python36/Lib/mimetypes.py">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="4879"> <state relative-caret-position="4879">
@ -1039,9 +879,6 @@
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/YtManager/settings.py">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/YtManagerApp/management/downloader.py"> <entry file="file://$PROJECT_DIR$/YtManagerApp/management/downloader.py">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="126"> <state relative-caret-position="126">
@ -1064,17 +901,14 @@
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/YtManagerApp/management/jobs/synchronize.py"> <entry file="file://$PROJECT_DIR$/YtManagerApp/views/actions.py">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="119"> <state relative-caret-position="483">
<caret line="7" selection-start-line="7" selection-end-line="7" selection-end-column="60" /> <caret line="58" selection-start-line="58" selection-end-line="58" />
</state> <folding>
</provider> <element signature="e#0#73#0" expanded="true" />
</entry> <marker date="1540074642385" expanded="true" signature="714:719" ph="..." />
<entry file="file://$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/index_videos.html"> </folding>
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="17">
<caret line="19" column="38" selection-start-line="19" selection-start-column="38" selection-end-line="19" selection-end-column="38" />
</state> </state>
</provider> </provider>
</entry> </entry>
@ -1088,13 +922,54 @@
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/YtManagerApp/views/actions.py"> <entry file="file://$PROJECT_DIR$/YtManagerApp/utils/iterutils.py">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="459"> <state relative-caret-position="544">
<caret line="58" lean-forward="true" selection-start-line="58" selection-end-line="58" /> <caret line="32" selection-start-line="32" selection-end-line="32" />
<folding> <folding>
<element signature="e#0#73#0" expanded="true" /> <element signature="e#0#16#0" expanded="true" />
<marker date="1540074642385" expanded="true" signature="714:719" ph="..." /> </folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/YtManagerApp/utils/youtube.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="187">
<caret line="11" lean-forward="true" selection-start-line="11" selection-end-line="11" />
<folding>
<element signature="e#0#43#0" expanded="true" />
<marker date="1540123481417" expanded="true" signature="487:699" ph="..." />
<marker date="1540123481417" expanded="true" signature="3562:4080" ph="..." />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/YtManagerApp/management/jobs/synchronize.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-855">
<caret line="34" column="49" selection-start-line="34" selection-start-column="49" selection-end-line="34" selection-end-column="49" />
<folding>
<element signature="e#0#49#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/YtManagerApp/management/videos.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="357">
<caret line="24" column="9" lean-forward="true" selection-start-line="24" selection-start-column="9" selection-end-line="24" selection-end-column="9" />
<folding>
<element signature="e#0#71#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/YtManagerApp/scheduler.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="102">
<caret line="6" selection-start-line="6" selection-end-line="6" />
<folding>
<element signature="e#0#14#0" expanded="true" />
</folding> </folding>
</state> </state>
</provider> </provider>
@ -1106,22 +981,8 @@
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/YtManagerApp/scheduler.py"> <entry file="file://$PROJECT_DIR$/config/config.ini">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor" />
<state relative-caret-position="102">
<caret line="6" lean-forward="true" selection-start-line="6" selection-end-line="6" />
<folding>
<element signature="e#0#14#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/YtManagerApp/management/jobs/delete_video.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="68">
<caret line="4" selection-start-line="4" selection-end-line="4" />
</state>
</provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/YtManagerApp/models.py"> <entry file="file://$PROJECT_DIR$/YtManagerApp/models.py">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
@ -1141,5 +1002,82 @@
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/YtManagerApp/management/jobs/delete_video.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="68">
<caret line="4" selection-start-line="4" selection-end-line="4" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/YtManager/settings.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="289">
<caret line="44" column="1" lean-forward="true" selection-start-line="44" selection-start-column="1" selection-end-line="44" selection-end-column="1" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/YtManagerApp/views/index.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="420">
<caret line="159" column="32" lean-forward="true" selection-start-line="159" selection-start-column="32" selection-end-line="159" selection-end-column="32" />
<folding>
<element signature="e#0#42#0" expanded="true" />
<marker date="1540023237405" expanded="true" signature="3128:3307" ph="..." />
<marker date="1540023237405" expanded="true" signature="3339:3340" ph="..." />
<marker date="1540023237405" expanded="true" signature="3646:3647" ph="..." />
<marker date="1540023237405" expanded="true" signature="3646:4387" ph="..." />
<marker date="1540023237405" expanded="true" signature="3668:4279" ph="..." />
<marker date="1540023237405" expanded="true" signature="4432:4436" ph="..." />
<marker date="1540023237405" expanded="true" signature="5221:6592" ph="..." />
<marker date="1540023237405" expanded="true" signature="5465:5470" ph="..." />
<marker date="1540023237405" expanded="true" signature="5491:5566" ph="..." />
<marker date="1540023237405" expanded="true" signature="6640:6641" ph="..." />
<marker date="1540023237405" expanded="true" signature="7201:7204" ph="..." />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/YtManagerApp/templatetags/common.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="459">
<caret line="30" lean-forward="true" selection-start-line="30" selection-end-line="30" />
</state>
</provider>
</entry>
<entry file="das://2dac2136-d902-4d27-8789-9371934602fd/schema/main/table/ytmanagerapp_video">
<provider selected="true" editor-type-id="com.intellij.database.editor.DatabaseTableFileEditorProvider">
<state>
<filtering enabled="true" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/YtManagerApp/templatetags/ratings.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="187">
<caret line="30" column="9" lean-forward="true" selection-start-line="30" selection-start-column="9" selection-end-line="30" selection-end-column="9" />
</state>
</provider>
</entry>
<entry file="file://C:/Python36/Lib/site-packages/django/template/base.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="279">
<caret line="759" column="23" selection-start-line="759" selection-start-column="23" selection-end-line="759" selection-end-column="23" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/YtManagerApp/static/YtManagerApp/css/style.scss">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="527">
<caret line="145" column="1" lean-forward="true" selection-start-line="145" selection-start-column="1" selection-end-line="145" selection-end-column="1" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/YtManagerApp/templates/YtManagerApp/index_videos.html">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="391">
<caret line="23" column="56" selection-start-line="23" selection-start-column="56" selection-end-line="23" selection-end-column="56" />
</state>
</provider>
</entry>
</component> </component>
</project> </project>

View File

@ -41,6 +41,7 @@ INSTALLED_APPS = [
'django.contrib.sessions', 'django.contrib.sessions',
'django.contrib.messages', 'django.contrib.messages',
'django.contrib.staticfiles', 'django.contrib.staticfiles',
'django.contrib.humanize'
] ]
MIDDLEWARE = [ MIDDLEWARE = [

View File

@ -21,10 +21,15 @@ def __check_new_videos_sub(subscription: Subscription, yt_api: YoutubeAPI):
results = Video.objects.filter(video_id=video.getVideoId(), subscription=subscription) results = Video.objects.filter(video_id=video.getVideoId(), subscription=subscription)
if len(results) == 0: if len(results) == 0:
log.info('New video for subscription %s: %s %s"', subscription, video.getVideoId(), video.getTitle()) log.info('New video for subscription %s: %s %s"', subscription, video.getVideoId(), video.getTitle())
create_video(video, subscription) db_video = create_video(video, subscription)
else: else:
# TODO... update view count, rating etc db_video = results.first()
pass
# Update video stats - rating and view count
stats = yt_api.get_single_video_stats(db_video.video_id)
db_video.rating = stats.get_like_count() / (stats.get_like_count() + stats.get_dislike_count())
db_video.views = stats.get_view_count()
db_video.save()
def __detect_deleted(subscription: Subscription): def __detect_deleted(subscription: Subscription):

View File

@ -19,6 +19,7 @@ def create_video(yt_video: YoutubePlaylistItem, subscription: Subscription):
video.icon_default = yt_video.getDefaultThumbnailUrl() video.icon_default = yt_video.getDefaultThumbnailUrl()
video.icon_best = yt_video.getBestThumbnailUrl() video.icon_best = yt_video.getBestThumbnailUrl()
video.save() video.save()
return video
def get_videos(user: User, def get_videos(user: User,

View File

@ -92,6 +92,8 @@
margin-right: -0.25rem; } margin-right: -0.25rem; }
.video-gallery .card .card-more:hover { .video-gallery .card .card-more:hover {
text-decoration: none; } text-decoration: none; }
.video-gallery .card .progress {
width: 100px; }
.video-gallery .video-icon-yes { .video-gallery .video-icon-yes {
color: #007bff; } color: #007bff; }
.video-gallery .video-icon-no { .video-gallery .video-icon-no {
@ -110,4 +112,8 @@
.modal-field-error ul { .modal-field-error ul {
margin: 0; } margin: 0; }
.star-rating {
display: inline-block;
margin-bottom: 0.5rem; }
/*# sourceMappingURL=style.css.map */ /*# sourceMappingURL=style.css.map */

View File

@ -1,6 +1,6 @@
{ {
"version": 3, "version": 3,
"mappings": "AAEA,OAAQ;EACJ,QAAQ,EAAE,KAAK;EACf,IAAI,EAAE,CAAC;EACP,KAAK,EAAE,CAAC;EACR,MAAM,EAAE,CAAC;EACT,MAAM,EAAE,IAAI;EACZ,WAAW,EAAE,IAAI;EACjB,OAAO,EAAE,SAAS;EAClB,OAAO,EAAE,IAAI;EACb,aAAa,EAAE,MAAM;EACrB,SAAS,EAAE,IAAI;;AAqBnB,uBAAuB;AACvB,kBAAmB;EAlBf,OAAO,EAAE,YAAY;EACrB,KAAK,EAAE,IAAa;EACpB,MAAM,EAAE,IAAa;EAErB,wBAAQ;IACJ,OAAO,EAAE,GAAG;IACZ,OAAO,EAAE,KAAK;IACd,KAAK,EAAE,IAAa;IACpB,MAAM,EAAE,IAAa;IACrB,MAAM,EAAE,GAAG;IACX,aAAa,EAAE,GAAG;IAClB,MAAM,EAAE,iBAAkC;IAC1C,YAAY,EAAE,uCAAmD;IACjE,SAAS,EAAE,sCAAsC;;AASzD,wBAAyB;EAtBrB,OAAO,EAAE,YAAY;EACrB,KAAK,EAAE,IAAa;EACpB,MAAM,EAAE,IAAa;EAErB,8BAAQ;IACJ,OAAO,EAAE,GAAG;IACZ,OAAO,EAAE,KAAK;IACd,KAAK,EAAE,IAAa;IACpB,MAAM,EAAE,IAAa;IACrB,MAAM,EAAE,GAAG;IACX,aAAa,EAAE,GAAG;IAClB,MAAM,EAAE,mBAAkC;IAC1C,YAAY,EAAE,uCAAmD;IACjE,SAAS,EAAE,sCAAsC;;AAazD,4BAOC;EANG,EAAG;IACC,SAAS,EAAE,YAAY;EAE3B,IAAK;IACD,SAAS,EAAE,cAAc;AAIjC,gCAAiC;EAC7B,QAAQ,EAAE,KAAK;EACf,GAAG,EAAE,GAAG;EACR,IAAI,EAAE,GAAG;EACT,UAAU,EAAE,KAAK;EACjB,WAAW,EAAE,KAAK;;AAGtB,cAAe;EACX,QAAQ,EAAE,KAAK;EAAE,oCAAoC;EACrD,OAAO,EAAE,IAAI;EAAE,uBAAuB;EACtC,KAAK,EAAE,IAAI;EAAE,uCAAuC;EACpD,MAAM,EAAE,IAAI;EAAE,wCAAwC;EACtD,GAAG,EAAE,CAAC;EACN,IAAI,EAAE,CAAC;EACP,KAAK,EAAE,CAAC;EACR,MAAM,EAAE,CAAC;EACT,gBAAgB,EAAE,kBAAe;EAAE,mCAAmC;EACtE,OAAO,EAAE,CAAC;EAAE,qFAAqF;EACjG,MAAM,EAAE,OAAO;EAAE,4BAA4B;;AAI7C,4BAAc;EACV,OAAO,EAAE,MAAM;EACf,aAAa,EAAE,KAAK;AAGpB,+BAAW;EACP,OAAO,EAAE,MAAM;AAEnB,+BAAW;EACP,SAAS,EAAE,IAAI;EACf,aAAa,EAAE,KAAK;AAExB,gCAAY;EACR,SAAS,EAAE,IAAI;EACf,aAAa,EAAE,KAAK;EAEpB,uCAAO;IACH,SAAS,EAAE,GAAG;AAGtB,iCAAa;EACT,OAAO,EAAE,YAAY;AAGzB,+BAAW;EACP,YAAY,EAAE,QAAQ;EACtB,qCAAQ;IACJ,eAAe,EAAE,IAAI;AASjC,8BAAgB;EACZ,KAAK,EA/GE,OAAO;AAiHlB,6BAAe;EACX,KAAK,EAAE,OAAO;;AAItB,WAAY;EACR,SAAS,EAAE,KAAK;EAChB,MAAM,EAAE,MAAM;;AAId,2BAAe;EACX,OAAO,EAAE,IAAI;;AAIrB,kBAAmB;EACf,MAAM,EAAE,QAAQ;EAChB,OAAO,EAAE,QAAQ;EAEjB,qBAAG;IACC,MAAM,EAAE,CAAC", "mappings": "AAEA,OAAQ;EACJ,QAAQ,EAAE,KAAK;EACf,IAAI,EAAE,CAAC;EACP,KAAK,EAAE,CAAC;EACR,MAAM,EAAE,CAAC;EACT,MAAM,EAAE,IAAI;EACZ,WAAW,EAAE,IAAI;EACjB,OAAO,EAAE,SAAS;EAClB,OAAO,EAAE,IAAI;EACb,aAAa,EAAE,MAAM;EACrB,SAAS,EAAE,IAAI;;AAqBnB,uBAAuB;AACvB,kBAAmB;EAlBf,OAAO,EAAE,YAAY;EACrB,KAAK,EAAE,IAAa;EACpB,MAAM,EAAE,IAAa;EAErB,wBAAQ;IACJ,OAAO,EAAE,GAAG;IACZ,OAAO,EAAE,KAAK;IACd,KAAK,EAAE,IAAa;IACpB,MAAM,EAAE,IAAa;IACrB,MAAM,EAAE,GAAG;IACX,aAAa,EAAE,GAAG;IAClB,MAAM,EAAE,iBAAkC;IAC1C,YAAY,EAAE,uCAAmD;IACjE,SAAS,EAAE,sCAAsC;;AASzD,wBAAyB;EAtBrB,OAAO,EAAE,YAAY;EACrB,KAAK,EAAE,IAAa;EACpB,MAAM,EAAE,IAAa;EAErB,8BAAQ;IACJ,OAAO,EAAE,GAAG;IACZ,OAAO,EAAE,KAAK;IACd,KAAK,EAAE,IAAa;IACpB,MAAM,EAAE,IAAa;IACrB,MAAM,EAAE,GAAG;IACX,aAAa,EAAE,GAAG;IAClB,MAAM,EAAE,mBAAkC;IAC1C,YAAY,EAAE,uCAAmD;IACjE,SAAS,EAAE,sCAAsC;;AAazD,4BAOC;EANG,EAAG;IACC,SAAS,EAAE,YAAY;EAE3B,IAAK;IACD,SAAS,EAAE,cAAc;AAIjC,gCAAiC;EAC7B,QAAQ,EAAE,KAAK;EACf,GAAG,EAAE,GAAG;EACR,IAAI,EAAE,GAAG;EACT,UAAU,EAAE,KAAK;EACjB,WAAW,EAAE,KAAK;;AAGtB,cAAe;EACX,QAAQ,EAAE,KAAK;EAAE,oCAAoC;EACrD,OAAO,EAAE,IAAI;EAAE,uBAAuB;EACtC,KAAK,EAAE,IAAI;EAAE,uCAAuC;EACpD,MAAM,EAAE,IAAI;EAAE,wCAAwC;EACtD,GAAG,EAAE,CAAC;EACN,IAAI,EAAE,CAAC;EACP,KAAK,EAAE,CAAC;EACR,MAAM,EAAE,CAAC;EACT,gBAAgB,EAAE,kBAAe;EAAE,mCAAmC;EACtE,OAAO,EAAE,CAAC;EAAE,qFAAqF;EACjG,MAAM,EAAE,OAAO;EAAE,4BAA4B;;AAI7C,4BAAc;EACV,OAAO,EAAE,MAAM;EACf,aAAa,EAAE,KAAK;AAGpB,+BAAW;EACP,OAAO,EAAE,MAAM;AAEnB,+BAAW;EACP,SAAS,EAAE,IAAI;EACf,aAAa,EAAE,KAAK;AAExB,gCAAY;EACR,SAAS,EAAE,IAAI;EACf,aAAa,EAAE,KAAK;EAEpB,uCAAO;IACH,SAAS,EAAE,GAAG;AAGtB,iCAAa;EACT,OAAO,EAAE,YAAY;AAGzB,+BAAW;EACP,YAAY,EAAE,QAAQ;EACtB,qCAAQ;IACJ,eAAe,EAAE,IAAI;AAO7B,8BAAU;EACN,KAAK,EAAE,KAAK;AAKpB,8BAAgB;EACZ,KAAK,EAnHE,OAAO;AAqHlB,6BAAe;EACX,KAAK,EAAE,OAAO;;AAItB,WAAY;EACR,SAAS,EAAE,KAAK;EAChB,MAAM,EAAE,MAAM;;AAId,2BAAe;EACX,OAAO,EAAE,IAAI;;AAIrB,kBAAmB;EACf,MAAM,EAAE,QAAQ;EAChB,OAAO,EAAE,QAAQ;EAEjB,qBAAG;IACC,MAAM,EAAE,CAAC;;AAIjB,YAAa;EACT,OAAO,EAAE,YAAY;EACrB,aAAa,EAAE,MAAM",
"sources": ["style.scss"], "sources": ["style.scss"],
"names": [], "names": [],
"file": "style.css" "file": "style.css"

View File

@ -104,8 +104,12 @@ $accent-color: #007bff;
} }
.card-img-top { .card-img-top {
} }
.progress {
width: 100px;
}
} }
.video-icon-yes { .video-icon-yes {
@ -134,5 +138,9 @@ $accent-color: #007bff;
ul { ul {
margin: 0; margin: 0;
} }
}
.star-rating {
display: inline-block;
margin-bottom: 0.5rem;
} }

View File

@ -1,3 +1,6 @@
{% load humanize %}
{% load ratings %}
<div class="video-gallery container-fluid"> <div class="video-gallery container-fluid">
<div class="row"> <div class="row">
{% for video in videos %} {% for video in videos %}
@ -11,6 +14,11 @@
{% endif %} {% endif %}
{{ video.name }} {{ video.name }}
</h5> </h5>
<p class="card-text small text-muted">
<span>{{ video.views | intcomma }} views</span>
<span>&#x2022;</span>
<span>{{ video.publish_date | naturaltime }}</span>
</p>
<p class="card-text">{{ video.description | truncatechars:120 }}</p> <p class="card-text">{{ video.description | truncatechars:120 }}</p>
</div> </div>
<div class="card-footer dropdown show"> <div class="card-footer dropdown show">

View File

View File

@ -0,0 +1,30 @@
from django import template
register = template.Library()
class SetVarNode(template.Node):
def __init__(self, var_name, var_value):
self.var_name = var_name
self.var_value = var_value
def render(self, context):
try:
value = template.Variable(self.var_value).resolve(context)
except template.VariableDoesNotExist:
value = ""
context[self.var_name] = value
return u""
@register.tag(name='set')
def set_var(parser, token):
"""
{% set some_var = '123' %}
"""
parts = token.split_contents()
if len(parts) < 4:
raise template.TemplateSyntaxError("'set' tag must be of the form: {% set <var_name> = <var_value> %}")
return SetVarNode(parts[1], parts[3])

View File

@ -0,0 +1,61 @@
from django import template
register = template.Library()
FULL_STAR_CLASS = "typcn-star-full-outline"
HALF_STAR_CLASS = "typcn-star-half-outline"
EMPTY_STAR_CLASS = "typcn-star-outline"
class StarRatingNode(template.Node):
def __init__(self, rating_percent, max_stars="5"):
self.rating = rating_percent
self.max_stars = max_stars
def render(self, context):
try:
rating = template.Variable(self.rating).resolve(context)
except template.VariableDoesNotExist:
rating = 0
try:
max_stars = template.Variable(self.max_stars).resolve(context)
except template.VariableDoesNotExist:
max_stars = 0
total_halves = (max_stars - 1) * rating * 2
html = [
f'<div class="star-rating" title="{ 1 + (total_halves / 2):.2f} stars">'
f'<span class="typcn {FULL_STAR_CLASS}"></span>'
]
for i in range(max_stars - 1):
if total_halves >= 2 * i + 2:
cls = FULL_STAR_CLASS
elif total_halves >= 2 * i + 1:
cls = HALF_STAR_CLASS
else:
cls = EMPTY_STAR_CLASS
html.append(f'<span class="typcn {cls}"></span>')
html.append("</div>")
return u"".join(html)
@register.tag(name='starrating')
def star_rating_tag(parser, token):
"""
{% rating percent [max_stars=5]%}
"""
parts = token.split_contents()
if len(parts) <= 1:
raise template.TemplateSyntaxError("'set' tag must be of the form: {% rating <value_percent> [<max_stars>=5] %}")
if len(parts) <= 2:
return StarRatingNode(parts[1])
return StarRatingNode(parts[1], parts[2])

View File

@ -1,3 +1,7 @@
import itertools
from typing import Iterable
def first_true(*args, default=False, pred=None): def first_true(*args, default=False, pred=None):
"""Returns the first true value in the iterable. """Returns the first true value in the iterable.
@ -10,3 +14,19 @@ def first_true(*args, default=False, pred=None):
# first_true([a,b,c], x) --> a or b or c or x # first_true([a,b,c], x) --> a or b or c or x
# first_true([a,b], x, f) --> a if f(a) else b if f(b) else x # first_true([a,b], x, f) --> a if f(a) else b if f(b) else x
return next(filter(pred, args), default) return next(filter(pred, args), default)
def as_chunks(iterable: Iterable, chunk_size: int):
"""
Iterates an iterable in chunks of chunk_size elements.
:param iterable: An iterable containing items to iterate.
:param chunk_size: Chunk size
:return: Returns a generator which will yield chunks of size chunk_size
"""
it = iter(iterable)
while True:
chunk = tuple(itertools.islice(it, chunk_size))
if not chunk:
return
yield chunk

View File

@ -3,10 +3,13 @@ from googleapiclient.errors import Error as APIError
from google_auth_oauthlib.flow import InstalledAppFlow from google_auth_oauthlib.flow import InstalledAppFlow
from django.conf import settings from django.conf import settings
import re import re
from YtManagerApp.utils.iterutils import as_chunks
API_SERVICE_NAME = 'youtube' API_SERVICE_NAME = 'youtube'
API_VERSION = 'v3' API_VERSION = 'v3'
YOUTUBE_LIST_LIMIT = 50
class YoutubeException(Exception): class YoutubeException(Exception):
pass pass
@ -28,6 +31,10 @@ class YoutubePlaylistNotFoundException(YoutubeException):
pass pass
class YoutubeVideoNotFoundException(YoutubeException):
pass
class YoutubeChannelInfo(object): class YoutubeChannelInfo(object):
def __init__(self, result_dict): def __init__(self, result_dict):
self.__id = result_dict['id'] self.__id = result_dict['id']
@ -130,6 +137,27 @@ class YoutubePlaylistItem(object):
return self.__snippet['position'] return self.__snippet['position']
class YoutubeVideoStatistics(object):
def __init__(self, result_dict):
self.id = result_dict['id']
self.stats = result_dict['statistics']
def get_view_count(self):
return int(self.stats['viewCount'])
def get_like_count(self):
return int(self.stats['likeCount'])
def get_dislike_count(self):
return int(self.stats['dislikeCount'])
def get_favorite_count(self):
return int(self.stats['favoriteCount'])
def get_comment_count(self):
return int(self.stats['commentCount'])
class YoutubeAPI(object): class YoutubeAPI(object):
def __init__(self, service): def __init__(self, service):
self.service = service self.service = service
@ -230,6 +258,26 @@ class YoutubeAPI(object):
else: else:
last_page = True last_page = True
def get_single_video_stats(self, video_id) -> YoutubeVideoStatistics:
result = list(self.get_video_stats([video_id]))
if len(result) < 1:
raise YoutubeVideoNotFoundException('Could not find video with id ' + video_id + '!')
return result[0]
def get_video_stats(self, video_id_list):
for chunk in as_chunks(video_id_list, YOUTUBE_LIST_LIMIT):
kwargs = {
"part": "statistics",
"maxResults": YOUTUBE_LIST_LIMIT,
"id": ','.join(chunk)
}
result = self.service.videos()\
.list(**kwargs)\
.execute()
for item in result['items']:
yield YoutubeVideoStatistics(item)
# @staticmethod # @staticmethod
# def build_oauth() -> 'YoutubeAPI': # def build_oauth() -> 'YoutubeAPI':
# flow = # flow =