Permalink
Browse files

Tyggbot major update to 2.0

This update is incompatible with the databases from 1.0,
follow the steps in the wiki for how to keep your data.

Changes:
 * Changed SQL Library from pymysql to SQLAlchemy
 * Changed the way we handle DB revisions from writing MySQL
   queries in a python script to using the alembic library.
 * Parameters can be passed to some methods now, like
   !add command and !add banphrase. Example:
   !add command test --whisper Whisper me!
 * Moved the file structure around in preparation to try to make
   tyggbot into a proper python library!
  • Loading branch information...
1 parent 233f9e9 commit d34e8083acd0ba5bd8275f2edf5df7a56a926bbb @pajlada committed Nov 4, 2015
Showing with 2,034 additions and 1,442 deletions.
  1. +68 −0 alembic.ini
  2. +108 −0 alembic/env.py
  3. +24 −0 alembic/script.py.mako
  4. +37 −0 alembic/versions/46e47b8f160_added_the_deck_table.py
  5. +146 −0 alembic/versions/4f48d3dd0fb_initial_db_version.py
  6. +0 −242 command.py
  7. +0 −56 kvidata.py
  8. +11 −7 main.py
  9. +0 −141 models/emote.py
  10. +0 −86 models/linktracker.py
  11. +0 −22 models/setting.py
  12. +0 −187 models/user.py
  13. +12 −3 pip-requirements.txt
  14. +0 −120 scripts/database.py
  15. 0 { → tests}/tests.py
  16. 0 {scripts → tyggbot}/__init__.py
  17. 0 { → tyggbot}/actions.py
  18. 0 { → tyggbot}/apiwrappers.py
  19. +203 −203 { → tyggbot}/dispatch.py
  20. +1 −0 tyggbot/models/__init__.py
  21. +34 −3 tbactions.py → tyggbot/models/action.py
  22. 0 { → tyggbot}/models/cachedvalue.py
  23. +345 −0 tyggbot/models/command.py
  24. 0 { → tyggbot}/models/connection.py
  25. +23 −0 tyggbot/models/db.py
  26. +119 −0 tyggbot/models/emote.py
  27. +148 −0 tyggbot/models/filter.py
  28. +61 −0 tyggbot/models/kvi.py
  29. +118 −39 { → tyggbot}/models/linkchecker.py
  30. +68 −0 tyggbot/models/linktracker.py
  31. +56 −0 tyggbot/models/motd.py
  32. 0 { → tyggbot}/models/pyramidparser.py
  33. +71 −0 tyggbot/models/setting.py
  34. +28 −13 { → tyggbot}/models/twitter.py
  35. +163 −0 tyggbot/models/user.py
  36. 0 { → tyggbot}/models/websocket.py
  37. +19 −7 { → tyggbot}/models/whisperconnection.py
  38. 0 { → tyggbot/scripts}/__init__.py
  39. 0 { → tyggbot}/scripts/transfer-num-lines.py
  40. 0 { → tyggbot}/scripts/update_emotes.py
  41. 0 { → tyggbot}/tbmath.py
  42. +31 −2 { → tyggbot}/tbutil.py
  43. +140 −311 { → tyggbot}/tyggbot.py
View
@@ -0,0 +1,68 @@
+# A generic, single database configuration.
+
+[alembic]
+# path to migration scripts
+script_location = alembic
+
+# template used to generate migration files
+# file_template = %%(rev)s_%%(slug)s
+
+# max length of characters to apply to the
+# "slug" field
+#truncate_slug_length = 40
+
+# set to 'true' to run the environment during
+# the 'revision' command, regardless of autogenerate
+# revision_environment = false
+
+# set to 'true' to allow .pyc and .pyo files without
+# a source .py file to be detected as revisions in the
+# versions/ directory
+# sourceless = false
+
+# version location specification; this defaults
+# to alembic/versions. When using multiple version
+# directories, initial revisions must be specified with --version-path
+# version_locations = %(here)s/bar %(here)s/bat alembic/versions
+
+# the output encoding used when revision files
+# are written from script.py.mako
+# output_encoding = utf-8
+
+sqlalchemy.url = this_value_is_not_even_used
+
+
+# Logging configuration
+[loggers]
+keys = root,sqlalchemy,alembic
+
+[handlers]
+keys = console
+
+[formatters]
+keys = generic
+
+[logger_root]
+level = WARN
+handlers = console
+qualname =
+
+[logger_sqlalchemy]
+level = WARN
+handlers =
+qualname = sqlalchemy.engine
+
+[logger_alembic]
+level = INFO
+handlers =
+qualname = alembic
+
+[handler_console]
+class = StreamHandler
+args = (sys.stderr,)
+level = NOTSET
+formatter = generic
+
+[formatter_generic]
+format = %(levelname)-5.5s [%(name)s] %(message)s
+datefmt = %H:%M:%S
View
@@ -0,0 +1,108 @@
+from __future__ import with_statement
+import sys
+import os
+import argparse
+from alembic import context
+from sqlalchemy import engine_from_config, pool
+from logging.config import fileConfig
+
+
+sys.path.append(os.path.dirname(os.path.abspath(__file__ + '/..')))
+
+from tyggbot.tyggbot import TyggBot
+try:
+ from tyggbot.models.deck import Deck
+except:
+ pass
+from tyggbot.tbutil import load_config
+
+tag = context.get_tag_argument()
+
+parser = argparse.ArgumentParser()
+parser.add_argument('--config', '-c',
+ default='config.ini',
+ help='Specify which config file to use '
+ '(default: config.ini)')
+custom_args = None
+if tag is not None:
+ custom_args = tag.replace('"', '').split()
+args, unknown = parser.parse_known_args(args=custom_args)
+
+print('Loading config from {0}'.format(args.config))
+tb_config = load_config(args.config)
+
+from tyggbot.models.db import Base
+# from tyggbot.models.user import User
+# from tyggbot.models.command import Command
+# from tyggbot.models import *
+
+# from tyggbot.tbutil import load_config
+
+# this is the Alembic Config object, which provides
+# access to the values within the .ini file in use.
+config = context.config
+
+config.set_main_option('sqlalchemy.url', tb_config['main']['db'])
+
+# Interpret the config file for Python logging.
+# This line sets up loggers basically.
+fileConfig(config.config_file_name)
+
+# add your model's MetaData object here
+# for 'autogenerate' support
+# from myapp import mymodel
+# target_metadata = mymodel.Base.metadata
+target_metadata = Base.metadata
+# sys.exit(0)
+
+# other values from the config, defined by the needs of env.py,
+# can be acquired:
+# my_important_option = config.get_main_option("my_important_option")
+# ... etc.
+
+
+def run_migrations_offline():
+ """Run migrations in 'offline' mode.
+
+ This configures the context with just a URL
+ and not an Engine, though an Engine is acceptable
+ here as well. By skipping the Engine creation
+ we don't even need a DBAPI to be available.
+
+ Calls to context.execute() here emit the given string to the
+ script output.
+
+ """
+ url = config.get_main_option("sqlalchemy.url")
+ context.configure(
+ url=url, target_metadata=target_metadata, literal_binds=True)
+
+ with context.begin_transaction():
+ context.run_migrations()
+
+
+def run_migrations_online():
+ """Run migrations in 'online' mode.
+
+ In this scenario we need to create an Engine
+ and associate a connection with the context.
+
+ """
+ connectable = engine_from_config(
+ config.get_section(config.config_ini_section),
+ prefix='sqlalchemy.',
+ poolclass=pool.NullPool)
+
+ with connectable.connect() as connection:
+ context.configure(
+ connection=connection,
+ target_metadata=target_metadata
+ )
+
+ with context.begin_transaction():
+ context.run_migrations()
+
+if context.is_offline_mode():
+ run_migrations_offline()
+else:
+ run_migrations_online()
@@ -0,0 +1,24 @@
+"""${message}
+
+Revision ID: ${up_revision}
+Revises: ${down_revision | comma,n}
+Create Date: ${create_date}
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = ${repr(up_revision)}
+down_revision = ${repr(down_revision)}
+branch_labels = ${repr(branch_labels)}
+depends_on = ${repr(depends_on)}
+
+from alembic import op
+import sqlalchemy as sa
+${imports if imports else ""}
+
+def upgrade():
+ ${upgrades if upgrades else "pass"}
+
+
+def downgrade():
+ ${downgrades if downgrades else "pass"}
@@ -0,0 +1,37 @@
+"""Added the deck table
+
+Revision ID: 46e47b8f160
+Revises: 4f48d3dd0fb
+Create Date: 2015-11-04 00:03:57.770809
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '46e47b8f160'
+down_revision = '4f48d3dd0fb'
+branch_labels = None
+depends_on = None
+
+from alembic import op
+import sqlalchemy as sa
+
+
+def upgrade():
+ ### commands auto generated by Alembic - please adjust! ###
+ op.create_table('tb_deck',
+ sa.Column('id', sa.Integer(), nullable=False),
+ sa.Column('name', sa.String(length=128), nullable=True),
+ sa.Column('class', sa.String(length=128), nullable=True),
+ sa.Column('link', sa.String(length=256), nullable=True),
+ sa.Column('first_used', sa.DateTime(), nullable=True),
+ sa.Column('last_used', sa.DateTime(), nullable=True),
+ sa.Column('times_used', sa.Integer(), nullable=True),
+ sa.PrimaryKeyConstraint('id')
+ )
+ ### end Alembic commands ###
+
+
+def downgrade():
+ ### commands auto generated by Alembic - please adjust! ###
+ op.drop_table('tb_deck')
+ ### end Alembic commands ###
@@ -0,0 +1,146 @@
+"""Initial DB Version
+
+Revision ID: 4f48d3dd0fb
+Revises:
+Create Date: 2015-11-03 17:19:00.113496
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '4f48d3dd0fb'
+down_revision = None
+branch_labels = None
+depends_on = None
+
+from alembic import op
+import sqlalchemy as sa
+from sqlalchemy.dialects import mysql
+
+def upgrade():
+ ### commands auto generated by Alembic - please adjust! ###
+ op.create_table('tb_commands',
+ sa.Column('id', sa.Integer(), nullable=False),
+ sa.Column('level', sa.Integer(), nullable=True),
+ sa.Column('action', mysql.TEXT(), nullable=True),
+ sa.Column('extra_args', mysql.TEXT(), nullable=True),
+ sa.Column('command', mysql.TEXT(), nullable=True),
+ sa.Column('description', mysql.TEXT(), nullable=True),
+ sa.Column('delay_all', sa.Integer(), nullable=True),
+ sa.Column('delay_user', sa.Integer(), nullable=True),
+ sa.Column('enabled', sa.Boolean(), nullable=True),
+ sa.Column('num_uses', sa.Integer(), nullable=True),
+ sa.Column('cost', sa.Integer(), nullable=True),
+ sa.Column('can_execute_with_whisper', sa.Boolean(), nullable=True),
+ sa.Column('sub_only', sa.Boolean(), nullable=True),
+ sa.Column('created', sa.DateTime(), nullable=True),
+ sa.Column('last_updated', sa.DateTime(), nullable=True),
+ sa.PrimaryKeyConstraint('id')
+ )
+ op.create_table('tb_emote',
+ sa.Column('id', sa.Integer(), nullable=False),
+ sa.Column('emote_id', sa.Integer(), nullable=True),
+ sa.Column('emote_hash', sa.String(length=32), nullable=True),
+ sa.Column('code', sa.String(length=64), nullable=True),
+ sa.Column('tm_record', sa.Integer(), nullable=True),
+ sa.Column('count', sa.Integer(), nullable=True),
+ sa.PrimaryKeyConstraint('id')
+ )
+ op.create_table('tb_filters',
+ sa.Column('id', sa.Integer(), nullable=False),
+ sa.Column('name', sa.String(length=128), nullable=True),
+ sa.Column('type', sa.String(length=64), nullable=True),
+ sa.Column('action', mysql.TEXT(), nullable=True),
+ sa.Column('extra_args', mysql.TEXT(), nullable=True),
+ sa.Column('filter', mysql.TEXT(), nullable=True),
+ sa.Column('source', mysql.TEXT(), nullable=True),
+ sa.Column('enabled', sa.Boolean(), nullable=True),
+ sa.Column('num_uses', sa.Integer(), nullable=True),
+ sa.PrimaryKeyConstraint('id')
+ )
+ op.create_table('tb_idata',
+ sa.Column('id', sa.String(length=64), nullable=False),
+ sa.Column('value', sa.Integer(), nullable=True),
+ sa.PrimaryKeyConstraint('id')
+ )
+ op.create_table('tb_link_blacklist',
+ sa.Column('id', sa.Integer(), nullable=False),
+ sa.Column('domain', sa.String(length=256), nullable=True),
+ sa.Column('path', mysql.TEXT(), nullable=True),
+ sa.Column('level', sa.Integer(), nullable=True),
+ sa.PrimaryKeyConstraint('id')
+ )
+ op.create_table('tb_link_data',
+ sa.Column('id', sa.Integer(), nullable=False),
+ sa.Column('url', mysql.TEXT(), nullable=True),
+ sa.Column('times_linked', sa.Integer(), nullable=True),
+ sa.Column('first_linked', sa.DateTime(), nullable=True),
+ sa.Column('last_linked', sa.DateTime(), nullable=True),
+ sa.PrimaryKeyConstraint('id')
+ )
+ op.create_table('tb_link_whitelist',
+ sa.Column('id', sa.Integer(), nullable=False),
+ sa.Column('domain', sa.String(length=256), nullable=True),
+ sa.Column('path', mysql.TEXT(), nullable=True),
+ sa.PrimaryKeyConstraint('id')
+ )
+ op.create_table('tb_motd',
+ sa.Column('id', sa.Integer(), nullable=False),
+ sa.Column('message', sa.String(length=400), nullable=True),
+ sa.Column('enabled', sa.Boolean(), nullable=True),
+ sa.PrimaryKeyConstraint('id')
+ )
+ op.create_table('tb_settings',
+ sa.Column('id', sa.Integer(), nullable=False),
+ sa.Column('setting', sa.String(length=128), nullable=True),
+ sa.Column('value', mysql.TEXT(), nullable=True),
+ sa.Column('type', sa.String(length=32), nullable=True),
+ sa.PrimaryKeyConstraint('id')
+ )
+ op.create_table('tb_twitter_following',
+ sa.Column('id', sa.Integer(), nullable=False),
+ sa.Column('username', sa.String(length=32), nullable=True),
+ sa.PrimaryKeyConstraint('id')
+ )
+ op.create_table('tb_user',
+ sa.Column('id', sa.Integer(), nullable=False),
+ sa.Column('username', sa.String(length=128), nullable=True),
+ sa.Column('username_raw', sa.String(length=128), nullable=True),
+ sa.Column('level', sa.Integer(), nullable=True),
+ sa.Column('points', sa.Integer(), nullable=True),
+ sa.Column('num_lines', sa.Integer(), nullable=True),
+ sa.Column('subscriber', sa.Boolean(), nullable=True),
+ sa.Column('last_seen', sa.DateTime(), nullable=True),
+ sa.Column('last_active', sa.DateTime(), nullable=True),
+ sa.Column('minutes_in_chat_online', sa.Integer(), nullable=True),
+ sa.Column('minutes_in_chat_offline', sa.Integer(), nullable=True),
+ sa.Column('twitch_access_token', sa.String(length=128), nullable=True),
+ sa.Column('twitch_refresh_token', sa.String(length=128), nullable=True),
+ sa.Column('discord_user_id', sa.String(length=32), nullable=True),
+ sa.Column('ignored', sa.Boolean(), nullable=True),
+ sa.Column('banned', sa.Boolean(), nullable=True),
+ sa.PrimaryKeyConstraint('id')
+ )
+ op.create_table('tb_whisper_account',
+ sa.Column('username', sa.String(length=128), nullable=False),
+ sa.Column('oauth', sa.String(length=128), nullable=True),
+ sa.Column('enabled', sa.Boolean(), nullable=True),
+ sa.PrimaryKeyConstraint('username')
+ )
+ ### end Alembic commands ###
+
+
+def downgrade():
+ ### commands auto generated by Alembic - please adjust! ###
+ op.drop_table('tb_whisper_account')
+ op.drop_table('tb_user')
+ op.drop_table('tb_twitter_following')
+ op.drop_table('tb_settings')
+ op.drop_table('tb_motd')
+ op.drop_table('tb_link_whitelist')
+ op.drop_table('tb_link_data')
+ op.drop_table('tb_link_blacklist')
+ op.drop_table('tb_idata')
+ op.drop_table('tb_filters')
+ op.drop_table('tb_emote')
+ op.drop_table('tb_commands')
+ ### end Alembic commands ###
Oops, something went wrong.

0 comments on commit d34e808

Please sign in to comment.